summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2013-02-13 00:03:06 +0000
committerKarl Berry <karl@freefriends.org>2013-02-13 00:03:06 +0000
commitfee6ae63b6689ddbae970ff9114c6ed976bf1dab (patch)
tree939a7748a57f664be54e21ea64d2168617f5d07c
parent4abc207ecf013eb27bf9f83c29b8a82408c9cd71 (diff)
skeyval (12feb13)
git-svn-id: svn://tug.org/texlive/trunk@29092 c570f23f-e606-0410-a88d-b1316a301751
-rw-r--r--Master/texmf-dist/doc/latex/skeyval/README445
-rw-r--r--Master/texmf-dist/doc/latex/skeyval/skeyval-pokayoke1.pdfbin126238 -> 126258 bytes
-rw-r--r--Master/texmf-dist/doc/latex/skeyval/skeyval-pokayoke1.tex166
-rw-r--r--Master/texmf-dist/doc/latex/skeyval/skeyval-pokayoke2.pdfbin136342 -> 136229 bytes
-rw-r--r--Master/texmf-dist/doc/latex/skeyval/skeyval-pokayoke2.tex68
-rw-r--r--Master/texmf-dist/doc/latex/skeyval/skeyval-testclass.cls51
-rw-r--r--Master/texmf-dist/doc/latex/skeyval/skeyval-testpkg.sty61
-rw-r--r--Master/texmf-dist/doc/latex/skeyval/skeyval-view-pokayoke1.pdfbin107744 -> 0 bytes
-rw-r--r--Master/texmf-dist/doc/latex/skeyval/skeyval-view-pokayoke1.tex139
-rw-r--r--Master/texmf-dist/tex/latex/skeyval/skeyval-bc.sty5
-rw-r--r--Master/texmf-dist/tex/latex/skeyval/skeyval-core.tex5115
-rw-r--r--Master/texmf-dist/tex/latex/skeyval/skeyval-for.tex823
-rw-r--r--Master/texmf-dist/tex/latex/skeyval/skeyval-ltxcmds.tex8
-rw-r--r--Master/texmf-dist/tex/latex/skeyval/skeyval-ltxpatch.sty6
-rw-r--r--Master/texmf-dist/tex/latex/skeyval/skeyval-pstkey.sty6
-rw-r--r--Master/texmf-dist/tex/latex/skeyval/skeyval-pstkey.tex8
-rw-r--r--Master/texmf-dist/tex/latex/skeyval/skeyval-view.sty33
-rw-r--r--Master/texmf-dist/tex/latex/skeyval/skeyval.sty797
18 files changed, 4865 insertions, 2866 deletions
diff --git a/Master/texmf-dist/doc/latex/skeyval/README b/Master/texmf-dist/doc/latex/skeyval/README
index 5a43e018146..00977c54e35 100644
--- a/Master/texmf-dist/doc/latex/skeyval/README
+++ b/Master/texmf-dist/doc/latex/skeyval/README
@@ -6,7 +6,7 @@ Ahmed Musa
VERSION
-Version 1.1a, October 16, 2012.
+Version 1.2, February 10, 2013.
LOCATION ON CTAN
@@ -14,7 +14,7 @@ macros/latex/contrib/skeyval
LICENSE
-Copyright (c) 2010-2012 Ahmed Musa
+Copyright (c) 2010-2013 Ahmed Musa
This software is author-maintained. Permission is granted to copy,
distribute and/or modify this software under the terms of the
@@ -60,19 +60,18 @@ The 's' in skeyval means 'skeleton keys' or 'master keys'.
The skeyval package provides commands for compactly defining and
initializing all types of key (ordinary, command, boolean, style, choice,
-etc). It attempts to combine the features of ltxkeys package (which has
-the syntax of the xkeyval package) and pgfkeys package. One of the powers
-of pgfkeys package lies in its use of handlers. But the way handlers
-are used in pgfkeys package does add to computational complexity and
-overheads. Family or key filtering in pgfkeys is particularly complex
-and inefficient. Nesting of family or key filtering is, in particular,
-not recommended.
+etc). It attempts to combine the features of xkeyval package and
+pgfkeys package. One of the powers of pgfkeys package lies in its use
+of handlers. But the way handlers are used in pgfkeys package does add
+to computational complexity and overheads. Family or key filtering in
+pgfkeys is particularly complex and inefficient. Nesting of family or
+key filtering is, in particular, not recommended.
In pgfkeys package, handlers come at the end of the key name, so that
if a key isn't defined, the system tests to find if the key has a
handler at its end. If a handler is found and defined, the handler's
callback (called 'code' by pgfkeys package) is executed on the
-current path.
+current path. The required search overhead isn't insignificant.
The skeyval package puts handlers at the beginning of the key
(or a set of keys) and uses the handler to process the key (or a set
@@ -81,12 +80,58 @@ complexity. Key processing, including filtering, can be nested
naturally and efficiently.
The skeyval package also maintains and, in fact, greatly extends the
-functionality and syntaxes of the ltxkeys package. Very few examples
-of the functionality of skeyval package are
+functionality and syntaxes of the xkeyval and ltxkeys packages.
-** The callbacks of keys can be readily modified using commands
- like \skvaddtocallback, \skvprependtocallback, \skvappendtocallback,
- or the handlers .prepend code, .append code, .add code.
+Some of the features of skeyval vs. xkeyval are as follows. All the
+features listed below could be incorporated in xkeyval package but
+at a great expense.
+
+* xkeyval's use of the rather expensive selective sanitization
+ scheme of Uwe Kern;
+
+* xkeyval strips three levels of outer braces in the values of keys;
+
+* the impossibility of parsing unbalanced conditionals in key values
+ while using xkeyval;
+
+* xkeyval requires a large payload for defining many keys in the
+ same family;
+
+* when using xkeyval, existing keys could be easily overridden
+ (there is nothing like \newcommand functionality);
+
+* key macros, once defined by xkeyval, are difficult to modify/patch;
+
+* key macros defined by xkeyval can't accept more than one argument;
+
+* xkeyval provides no machinery for deploying style (subject/observer)
+ keys;
+
+* xkeyval offers no direct tools for key-commands and key-environments;
+
+* xkeyval can't be loaded before \documentclass (eg, in the past the
+ fontspec package needed this feature);
+
+* skeyval offers 'list processor keys' (called 'listkeys').
+
+
+Very few examples of the functionality of skeyval package are given in
+the following.
+
+** Ordinary, command/store, boolean, toggle, and choice keys can be
+ defined and set. For example,
+
+ \skvordkeys[KV]{fam}{key1,key2}[default value]{%
+ \def\testcmd##1##2{#1+##1+##2}%
+ }
+ \skvoptionkeys[KV]{fam}{key1}
+ \skvnonoptionkeys[KV]{fam}{key2}
+
+ \skvchoicekeys[KV]{fam}[mp@]{key1,key2}[\val\nr]{%
+ center.do=\def\vala{#1},
+ right.do=\def\valb{#1},
+ left.do=\def\valc{#1}
+ }[center]{\def\x##1{#1*##1}}
** Apart from the usual keys in xkeyval and ltxkeys packages, it is
now possible to define a rather weird key like
@@ -112,6 +157,40 @@ of the functionality of skeyval package are
evaluate (\x) as (\pgfmathresult) using (\pgfmathparse{\x^10})
}
+** Default prefix can be set by
+
+ \skvsetdefaultprefix{<pref>}
+
+ For a fixed prefix, this can be used to avoid repeated entry of the
+ key prefix in many of the commands of the skeyval package. Note,
+ however, that the first '[]' in
+
+ \skvordkey[KV]{fam}{key1}[deafult value]{}
+
+ still can't be used for any other thing than the key prefix.
+
+ With
+
+ \skvsetdefaultprefix{myprefix}
+
+ we can do
+
+ \skvordkey{fam}{key1}[deafult1]{}
+ \skvcmdkey{fam}[mp@]{key2}[deafultx,defaulty]{%
+ \def\cmd##1{#1+#2+##1}%
+ }
+ \skvassignargs{fam}[.expanded]{key2}{#1,#2}
+
+ and much later
+
+ \def\valuex{valuex}
+ \def\valuey{valuey}
+ \skvsetkeys[myprefix]{fam}{key1=value1,key2={\valuex,\valuey}}
+
+** The callbacks of keys can be readily modified using commands
+ like \skvaddtocallback, \skvprependtocallback, \skvappendtocallback,
+ or the handlers .prepend code, .append code, .add code.
+
** Handlers
The skeyval package has many handlers. The handlers of
@@ -126,7 +205,7 @@ of the functionality of skeyval package are
introduced.
\skvappendstyles[KV]{fam}{key1,key2}{keya=.expanded{\vala},keyb=valb}
- [defaultof 1&2]{\def\y##1{#1*##1}}
+ [default of key1&2]{\def\y##1{#1*##1}}
Here the subjects are key1 and key2, while the observers are keya and
keyb. For now, the only thing the subject does is to set the given values
@@ -146,12 +225,13 @@ of the functionality of skeyval package are
\skvassignargs[KV1,KV2]{fam1,fam2}[x1]{keya,keyb}{#1/#2}
\skvsetkeys[KV1]{fam2}{keya=vala/valb}
- 'x1' here means expand argument once at setting keys.
+ 'x1' here means 'expand argument once at setting keys'.
+
+** \directkeys command:
\directkeys{%
.exec code=\def\avalue{a+b},
- .prefixes={KV1,KV2},
- .families={fam1,fam2},
+ .paths={KV1/fam1,KV1/fam2,KV2/fam1,KV2/fam2},
.holder prefix=mp@,
.initialize keys after define,
.define keys={
@@ -175,7 +255,7 @@ of the functionality of skeyval package are
\directkeys{
.default prefix=KV,
% The prefix for 'famx' will be 'KV'.
- .paths={KV3/fam3,famx},
+ .paths={KV3/fam3,KV3/famx},
.new keys={
.initialize keys after define=false,
.ord/keya/defa/\def\ya##1{#1*##1*#2},
@@ -207,7 +287,7 @@ of the functionality of skeyval package are
.prepend code={
keyb=\def\pre##1{#1+##1},
},
- .styles{
+ .slots{
key1/keya=value1,
key2/keyb=value2
},
@@ -219,6 +299,26 @@ of the functionality of skeyval package are
},
}
+** Handlers and letting handlers
+
+ The skeyval has many handlers and many tools for creating handlers.
+ A full listing of handlers and their meaning will be provided in
+ the user manual.
+
+ .define handlers, .define handler
+ .new handlers, .new handler
+ .new reserved handlers, .new reserved handler,
+ .define reserved handlers, .define reserved handler
+ .define narg handler,.define narg handlers
+ .new narg handler,.new narg handlers
+ .new reserved narg handler,.new reserved narg handlers,
+ .define reserved narg handler,.define reserved narg handlers
+ .handlers let, .handler let
+ .handlers let*, .handler let*, .force handler let
+ .handlers let reserved, .handler let reserved
+ .reserve handlers
+
+
** Prepending and appending to key names and callbacks at
definition time:
@@ -237,16 +337,15 @@ of the functionality of skeyval package are
** Several new features are introduced by the skeyval package. For
- example, we now have 'style' and 'link' keys in the context of
- ltxkeys syntax. For example, to link keys via .link or .style
- handler:
+ example, we now have 'slot' and 'link' keys. For example, to link
+ keys via .link or .slot handler, we can do:
\directkeys{%
.link={key1, key2}/keya,
.link={key3, key4}/{keya, keyb},
- .append style expand twice={key3, key4}/keyf=\valuea,
- .prepend style expanded={key5, key6}/{keyc=#1, keyd=#1},
- .prepend style={key7, key8}/{keyd=#1, keye=#1},
+ .append slot expand twice={key3, key4}/keyf=\valuea,
+ .prepend slot expanded={key5, key6}/{keyc=#1, keyd=#1},
+ .prepend slot={key7, key8}/{keyd=#1, keye=#1},
.allowed values expanded=keye/{
center.do=\def\curralign##1{\hfil##1\hfil},
right.do=\def\curralign##1{\hfill##1},
@@ -314,8 +413,12 @@ of the functionality of skeyval package are
** Keys can be 'made', as in
\skvmakekeys[
- .prefix=KVA, .families={fam1,fam2}, .holder prefix=mp@,
- .all are new, .define in all families, .initialize after define
+ .prefix=KVA,
+ .families={fam1,fam2},
+ .holder prefix=mp@,
+ .all are new,
+ .define in all families,
+ .initialize after define
]{%
.ord/{keya,keyb}/{default-a},
.arg/keyb/{#1+#2},
@@ -360,7 +463,7 @@ of the functionality of skeyval package are
\fi
}
\newcommand*\drawcoloredarrows[1]{%
- \foreacfox {#1}{%
+ \foreachfox {#1}{%
\draw[\usecolor{##1},-stealth] (0,-##1)--(2,-##1);
}
}
@@ -370,7 +473,184 @@ of the functionality of skeyval package are
\end{tikzpicture}
\end{document}
-** Keys defined in families can be viewed in files using the package
+** Arguments of keys:
+
+ Argument of keys can be prescribed
+
+ 1. Within the key's callback by using the pointers
+
+ .arg, .arg unexpanded, .arg expand once, .arg expand twice,
+ .arg expanded.
+
+ Example:
+
+ \def\somemethod#1#2{%
+ \begingroup
+ \color{#1}%
+ Using \ifskvnovalue default\else user \fi value of `\skvcurrentkey'.
+ \endgraf
+ Argument-2 of key: #2%
+ \endgroup
+ }
+ % Test arguments given inside the callback:
+ \skvcmdkeys[KV]{fam}{keya}[red/default]{%
+ .arg expanded{#1/#2}%
+ \somemethod{#1}{#2}%
+ }
+ \begin{document}
+ \def\aval{blue/Some stuff}
+ \skvsetkeys[KV]{fam}{keya=\aval}
+ \end{document}
+
+ 2. By calling the command \skvassignargs.
+
+ 3. By using the following handlers within \directkeys or within
+ \skvdefinekeys
+
+ .arg, .arg unexpanded, .arg expand once, .arg expand twice,
+ .arg expanded
+
+
+** Listkeys
+
+ List processor keys. The key's value is considered a csv list
+ and each of its element is used as the argument of the key's callback.
+ The user of a listkey doesn't have to define his own list processor,
+ or define one key for each list item. The list separator can be
+ arbitrary; it can be specified in the key's callback as the
+ argument of the dummy commands \listsep and \listparser. The default
+ list separator is comma (,).
+
+ \makeatletter
+ \def\somemethod#1#2{%
+ \begingroup
+ \color{#1}%
+ \ifskvnovalue
+ \ifnum\skvlistcount=\@ne
+ \endgraf
+ Using default value of `\skvcurrentkey':
+ \fi
+ \else
+ \ifnum\skvlistcount=\@ne
+ \endgraf
+ Using user value of `\skvcurrentkey':
+ \fi
+ \fi
+ \endgroup
+ \endgraf
+ Processing item no. \skvlistcount: #2%
+ }
+
+ % Use comma (,), the default list separator, as the list
+ % separator for keya and keyb:
+ \skvlistkeys[KV]{fam}{keya,keyb}[default1,default2]{%
+ \somemethod{blue}{#1}%
+ % Process only four (4) items of the list/value for keya and keyb:
+ \ifnum\skvlistcount=4\relax
+ \skvstopprocessinglistkey
+ \fi
+ }
+ %\skvshowcs{KV/fam/keya.@cbk}
+
+ % Use semicolon (;) as the list separator for keyc and keyd:
+ \skvlistkeys[KV]{fam}{keyc,keyd}[default1;default2]{%
+ % The next line gives error, as expected, since a list key
+ % can't have an assigned argument that isn't simple.
+ % .arg{#1,#2}%
+ \listsep{;}\somemethod{red}{#1}%
+ }
+ \makeatother
+
+ \begin{document}
+ \parindent0pt
+ % No values for keya and keyb; use their default values:
+ \skvsetkeys[KV]{fam}{keya,keyb}
+ \par\bigskip
+ \skvsetkeys[KV]{fam}{%
+ keya={item1A,item1B,item1C,item1D,item1E,item1F},
+ keyb={item2A,item2B,item2C,item2D,item2E,item2F}
+ }
+ \par\bigskip
+ % Set keyc and keyd with their default values:
+ \skvsetkeys[KV]{fam}{keyc,keyd}
+ \par\bigskip
+ \skvsetkeys[KV]{fam}{%
+ keyc={item1A;item1B;item1C;item1D},
+ keyd={item2A;item2B;item2C;item2D}
+ }
+ \end{document}
+
+** Make any key a listkeys at key-setting time
+
+ You can use the pointers '.process list' on any key's value at
+ key-setting time to temporarily turn that key into a listkey.
+ Its current value will be processed as a list, ie, the key's
+ callback will be applied to every element of the current value.
+ This scheme is costlier than defining the key as a listkey,
+ using \skvlistkey, but it is more versatile. This allows any
+ key to accept and process a value that is a list, irrespective
+ of its argument pattern.
+
+ Example 1:
+
+ \skvordkeys[KV]{fam}{key1,key2}[default]{\def\xx##1{##1*#1}}
+ \skvsetkeys[KV]{fam}{%
+ key1=val1,key2=.process list{val2a,val2b}
+ }
+
+ Example 2:
+
+ \skvordkeys[KV]{fam}{key1,key2}[default]{%
+ .arg expanded{#1/#2}%
+ \def\x##1{##1*#1*#2}%
+ }
+ \def\aval{val1a/val1b}
+ \def\bval{val2a/val2b,val2c/val2d}
+ \skvsetkeys[KV]{fam}{%
+ % Because of '.arg expanded' in the key's callback, \aval
+ % will be expanded at setting keys:
+ key1=\aval,
+ % \bval will be expanded before its content is processed
+ % as a list. Because of '.arg expanded' in the key's callback,
+ % each element in \bval will be expanded at setting keys:
+ key2=.expand once process list{\bval}
+ }
+
+ Example 3:
+
+ \skvordkeys[KV]{fam}{key1}[default]{\def\x##1{##1*#1}}
+ \def\aval{val1a,val1b,val1c,val1d}
+ \def\bval{\aval}
+ \def\cval{\bval}
+ \skvsetkeys[KV]{fam}{%
+ key1=.expand once process list{\aval},
+ key1=.expand twice process list{\bval},
+ key1=.expand process list{\cval}
+ }
+
+
+** Disabling keys:
+
+ Message type to be issued when a disabled key is called:
+
+ \skvmessagetypefordisabledkey{<message type>}
+
+ <message type> can be 'warning', 'error', or 'nothing'. The default is
+ 'warning'.
+
+ The key(s) may be disabled long before \skvmessagetypefordisabledkey
+ is called.
+
+ Disabling keys locally:
+
+ \skvdisablekeys[<pref>]{<fam>}{<key list>}
+
+ Disabling keys globally:
+
+ \skvgdisablekeys[<pref>]{<fam>}{<key list>}
+
+
+** Keys defined in families can be 'viewed' in files using the package
'skeyval-view'. The functionality of 'skeyval-view' is greater than
that of xkeyval-view package.
@@ -383,5 +663,106 @@ of the functionality of skeyval package are
module. It is a generalization of PGF's \foreach macro for
arbitrary parsers and list separators, including active parsers.
+** For a package 'foobar', you can access its options by
+
+ \csname opt@foobar.sty\endcsname
+
+ To get the options that were actually found/defined and instantiated
+ during the processing of options, the skeyval package offers
+ \skvpackagelist and '.poxkeys' (processed options).
+
+ If 'option1' and 'option2' (but not 'option3') are recognized
+ options of foobar.sty, then after
+
+ \usepackage[option1,option2,option3]{foobar}
+
+ you can issue
+
+ \show\skvpackagelist -> foobar.sty{option1,option2}
+
+ \expandafter\show\csname foobar.sty.poxkeys\endcsname
+ -> option1, option2
+
+** Key filtering
+
+ The handlers for key filtering are
+
+ .prefix, .change prefix, .family, .change family, .families,
+ .change families, .add family, .add families, .ignore family,
+ .ignore families, .restore family, .restore families, .paths,
+ .change path, .change paths, .add paths, .ignore paths, .restore paths,
+ .ignore keys, .restore keys
+
+ \newcommand{\storecontent}{}
+ \newcommand{\usecontent}{%
+ \ifx\storecontent\@empty
+ \@@warning{\noexpand\storecontent is empty}%
+ \else
+ \storecontent
+ \fi
+ }
+ \directkeys{%
+ % Define keys in two families:
+ .families={family1,family2},
+ .define ordinary keys={
+ store//\skvappendtomacro\storecontent{#1},
+ remove//\skvpatchcmd\storecontent{#1}{}{}{
+ \@@warning{No token '\detokenize{#1}' in command \string\storecontent}
+ }
+ }
+ }
+ \def\savpar{\par}
+ \def\bigvskip{\par\bigskip}
+ \def\showfam{Family: \skvcurrentfamily\savpar}
+
+ \begin{document}
+ \directkeys{%
+ % Set keys in only family1:
+ .family=family1,
+ .set keys={
+ store={\showfam first test\bigvskip},
+ store={\showfam second test\bigvskip}
+ },
+ .exec code=\usecontent{\color{red}\savpar\hrule\bigvskip},
+ % Set keys in only family2:
+ .family=family2,
+ .set keys={
+ remove={\showfam first test\bigvskip},
+ remove={\showfam second test\bigvskip},
+ store={\showfam third test\bigvskip},
+ store={\showfam fourth test\bigvskip}
+ },
+ .exec code=\usecontent
+ }
+ \end{document}
+
+** Inheritance of keys
+
+ There are \skvkeyslet with the syntax
+
+ \skvkeyslet[<pref>]{<family>}{<list>}
+ <list> -> {<newkey1>,<newkey2>,...,<newkey-n>}={<oldkey>}
+
+ and the handler .inherit.
+
+ \directkeys{
+ .prefix=KV,
+ .family=fam,
+ .define ordinary keys={
+ key1/def1/\def\cmd##1{#1*##1},
+ key2/def2
+ },
+ .inherit={
+ {key3,key4}={key1},
+ }
+ }
+ \skvshowcs{KV/fam/key3.@cbk}
+
+** Defining and setting keys on fixed prefix and family
+
+ \skvsetprefix{KV}
+ \skvsetfamily{fam}
+ \skvdefineordkey{key1}[def1]{\def\cmd##1{#1*##1}}
+ \skvprocesskeys{key1=value1}
-% End of readme file \ No newline at end of file
+% End of readme file of skeyval package.
diff --git a/Master/texmf-dist/doc/latex/skeyval/skeyval-pokayoke1.pdf b/Master/texmf-dist/doc/latex/skeyval/skeyval-pokayoke1.pdf
index aad9d8e117d..b38b077fa0a 100644
--- a/Master/texmf-dist/doc/latex/skeyval/skeyval-pokayoke1.pdf
+++ b/Master/texmf-dist/doc/latex/skeyval/skeyval-pokayoke1.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/skeyval/skeyval-pokayoke1.tex b/Master/texmf-dist/doc/latex/skeyval/skeyval-pokayoke1.tex
index 2be16f1aa95..ed79d37585d 100644
--- a/Master/texmf-dist/doc/latex/skeyval/skeyval-pokayoke1.tex
+++ b/Master/texmf-dist/doc/latex/skeyval/skeyval-pokayoke1.tex
@@ -12,12 +12,9 @@
watermarkcolor=brown!80!yellow
]{skeyval-testclass}
-%\show\@unusedoptionlist
-
-\skvifpackageloaded{xcolor}{}{\usepackage[dvipsname]{xcolor}}
+\skvifpackageloadedTF{xcolor}{}{\usepackage[dvipsname]{xcolor}}
\usepackage{lipsum}
-
% The command \cmdalign is just for illustrating how key values
% may be expanded at key setting time:
\def\cmdalign{justified}
@@ -29,14 +26,18 @@
unknown-option,
]{skeyval-testpkg}
-% Keys whose names are zapped internally:
-\skvzcmdkeys[KV]{fam}[mp@]{provide value,give value}[true]{}
+%+++++++++++ Keys whose names are zapped internally ++++++++++++++%
+
+\skvzcmdkeys[KV]{fam}[mp@]{provide value,give value}[some value]{}
\skvzboolkeys[KV]{fam}[mp@]{provide value,give value}[true]{}
-% Parenthesized keys are keys with names that have parentheses.
+%++++++++++++++++++++++ Parenthesized keys +++++++++++++++++++++++%
+
+% Parenthesized keys are keys with names that have parentheses
% The following is a key of 3 arguments. The default values are
-% \x, \y, and \numexpr\x*2.
-\skvpntkey[KV]{fam}{evaluate (?) as (?) using (?)}[\x\y{\numexpr\x*2}]{%
+% \x, \y, and \numexpr\x*2 - since there are 3 arguments.
+%
+\skvpntkey[KV]{fam}{evaluate (?) as (?) using (?)}[{\x}{\y}{\numexpr\x*2}]{%
\def\argone{#1}\def\argtwo{#2}\def\argthree{#3}%
% '\detokenize{\pgfmath}' won't work here!
\skvxifinTF{\relax\string\pgfmath}{\relax\detokenize{#3}}{%
@@ -47,6 +48,7 @@
}
% The above parenthesized key can be set as follows:
+%
\def\cmda{2}
\skvsetkeys[KV]{fam}{%
evaluate (\cmda) as (\cmdb) using (\pgfmathsetmacro\cmdb{\cmda*10})
@@ -56,29 +58,40 @@
\newcommand*\vgap{\endgraf\medskip}
\def\keycval{xx}
-%% +++++++++++++++ Examples of using \directkeys command +++++++++ %%
+%% +++++++++++++++ Examples of using \directkeys command ++++++++++%
% Note: When the value of a handler contains equality sign (=) or
% comma (,), it should be enclosed in braces.
+\directkeys*{%
+ % Defining new handlers that can't be overloaded:
+ .new reserved handlers={
+ {.x handler,.x handlers}={
+ \dirkeys@defhandlers{00}{#1}
+ },
+ }
+}
+
\directkeys*{
.exec=\skvtestcnt\z@,
.prefix = KV1,
.family = fam1,
.holder prefix = mp@,
.add paths={KV2/fam2,KV3/fam3},
- .ignore roots={KV2/fam2,KV3/fam3},
- .restore roots={KV2/fam2,KV3/fam3},
+ .ignore paths={KV2/fam2,KV3/fam3},
+ .restore paths={KV2/fam2,KV3/fam3},
.save initial values of keys,
.initialize keys after define=false,
.new keys = {
.ord/keya/{dfta,dftb}/
+ %\def\skvhp{my@}
\def\cmda##1{#1*##1*#2}\logsetting
- ,
+ ,
.arg/keya/{#1,#2},
+ % See argument of keyb below:
.cmd/keyb/{1cm,2cm}/
\edef\boxht{\the\dimexpr#1*2\relax}
- \edef\boxwd{\the\dimexpr#1*10\relax},
+ \edef\boxwd{\the\dimexpr#2*2\relax},
.choice/keyc/center/{right,left,center,justified},
.bool/keyd/true,
.cmd/keye/dfte/\def\cmde##1{##1#1},
@@ -102,66 +115,77 @@
.restore keys = keye,
.link={keye2/keye},
% Choices for keye can be declared directly:
- .estate pattern={keye,keye2}/{
+ .state pattern expanded={keye,keye2}/{
center.do=\def\curralign##1{\hfil##1\hfil},
right.do=\def\curralign##1{\hfill##1},
left.do=\def\curralign##1{##1\hfill},
justified.do=\let\curralign\@iden
},
- .exec code ={
+ .exec code={
\def\leftval{left}\def\rightval{right}
\def\rrightval{\rightval}
},
% key1 and key2 are undefined. They will be defined internally
% with the default values of keyc and keyd:
- .prepend style={
+ .prepend slots={
key1/{keyc=.expanded{\rightval}},key2/{keyd=false}
},
- .append style={
+ .append slots={
key1/{keye=right,keyf=valf}
},
% When key3 and key4 are set, use their expanded values to set keye:
.elink={
{key3,key4}/keye
},
- .style expand twice={
+ .slot expand twice={
key5/{keyf=#1,keyg=#1}
},
.set keys={
key3=.expand once{\leftval},
key5=.expand twice{\rrightval}
},
- .prepend link={
- {key6,key7}/{keye,keyf},{key8,key9}/{keye,keyg}
+ .prepend links={
+ {key6,key7}/{keye,keyf},
+ {key8,key9}/{keye,keyg}
},
.exec code=\skvsetkeys[KV1]{fam1}{key6=center},
% Set keya and keyb on previously declared and the following paths.
% Enter known keys in \mysuccesslist. Try 14 families; stop when
% 12 families have been hit (ie, keys have been set in them
% successfully):
+ .exec code=\def\flukepaths{},
.search also set keys={
- .add prefixes={KV3,KV4},
- .add families={fam3,fam4},
+ .paths={KX/famx,KV1/fam1,KV3/fam3,KV3/fam4,KV4/fam3,KV4/fam4},
+ .ignore keys={keyc},
.try=14,
- .upper goal=12,
+ .min success=10,
+ .max success=12,
.success list=\mysuccesslist,
- .kv={keya={val1,val2},keyb={1cm,2cm}}
+ .if any path fails={%
+ \edef\flukepaths{\skvaddlist,\flukepaths\skvcurrentpath}
+ },
+ .if hits less than goal={\skvsetkeys[KV1]{fam1}{keyc=center}},
+ .kv={keya={val1,val2},keyb={1cm,2cm},keyc}
},
% .exec code={\show\mysuccesslist},
\directkeys*{
.exec=\skvtestcnt\z@\def\mysuccesslist{},
- .paths={KUA/fam1,KUB/fam2},
- .define keys={
- .ord/{keya,keyb,keyc}/.na/
+ .paths={KUA/fam1,KUA/fam2,KUB/fam1,KUB/fam2},
+ .define ordinary keys={
+ {keya,keyb,keyc}/.na/
\def\y##1{#1*##1}
\typeout{***}\logsetting
+ \skvsetkeys[KV1]{fam1}{keyc=center}
,
}
},
% '.try set keys' works independent of previously declared paths:
.try set keys={
- .prefixes={KUA,KUB,KUC},
- .families={fam1,fam2,fam3,fam4},
+ .paths={
+ KUA/fam1,KUA/fam2,KUA/fam3,KUA/fam4,
+ KUB/fam1,KUB/fam2,KUB/fam3,KUB/fam4,
+ KUC/fam1,KUC/fam2,KUC/fam3,KUC/fam4
+ },
.try=8,
.upper goal=4,
.lower goal=2,
@@ -169,10 +193,10 @@
.success list=\mysuccesslist,
.kv={keya=vala,keyb=valb,keyc=valc}
},
-% .exec code={\show\mysuccesslist},
+%.exec code={\show\mysuccesslist},
}
-\dirkeys*{
+\directkeys*{
.exec=\skvtestcnt\z@\def\mysuccesslist{},
.paths={KUA/fam1,KUB/fam2},
.hp=mp@,
@@ -184,18 +208,17 @@
% keya has no default but has a complex callback:
.ord/keya/.na/{
\skvtestcnt\z@\def\mysuccesslistb{}
- \dirkeys{
+ \directkeys{
.path={KVX/famx},
- .sa set keys={%
- .prefixes={KUA,KUB},
- .families={fam1,fam2},
+ .search also set keys={%
+ .paths={KUA/fam1,KUA/fam2,KUB/fam1,KUB/fam2},
.try=8,
.upper goal=4,
.lower goal=1,
.success list=\mysuccesslistb,
.kv={keyb=valb}
},
-% .exec code=\show\mysuccesslistb,
+% .exec code=\show\mysuccesslistb,
}
}
,
@@ -211,8 +234,10 @@
}/.na/\@@warning{Invalid value '\detokenize{#1}' for keye2},
},
.try set keys={%
- .prefixes={KUA,KUB},
- .families={fam1,fam2,fam3,fam4},
+ .paths={
+ KUA/fam1,KUA/fam2,KUA/fam3,KUA/fam4,
+ KUB/fam1,KUB/fam2,KUB/fam3,KUB/fam4
+ },
.try=1,
.upper goal=1,
.lower goal=1,
@@ -226,7 +251,6 @@
\makeatother
\begin{document}
-
\title{The \texttt{\textcolor{blue}{skeyval}} Package\\[1ex]
Version 1.1a\\[1ex]
\textsf{Test document 1}}
@@ -251,7 +275,6 @@ return to their own country.
\hfill{\small Hieronymus Hornschuch (1608)}\endgraf
\end{\mpfalign}
-
\begingroup
\par\bigskip
\noindent
@@ -356,10 +379,21 @@ on their deeds.
\lipsum[1]
\end{collectbody}
-
\end{document}
+%%+++++++++++++++++++++ Assigning arguments to keys +++++++++++++++++%%
+
+\skvsetdefaultprefix{myprefix}
+\skvordkey{fam}{key1}[deafult1]{}
+\skvcmdkey{fam}[mp@]{key2}[deafultx,defaulty]{%
+ \def\cmd##1{#1+#2+##1}%
+}
+\skvassignargs{fam}[.expanded]{key2}{#1,#2}
+\def\valuex{valuex}
+\def\valuey{valuey}
+\skvsetkeys[myprefix]{fam}{key1=value1,key2={\valuex,\valuey}}
+
%%+++++++++++++++++++++ Examples of \skvmakekeys +++++++++++++++++++%%
\skvmakekeys[
@@ -481,6 +515,52 @@ on their deeds.
}
\makeatother
-% End of file skeyval-pokayoke1.tex
+%++++++++++++++++++++++++ \ifcases ++++++++++++++++++++++++++++++%
+\skvifcases b\then
+ case{a}{\def\x{do a}}
+ case{b}{\def\x{do b}}
+ case{c}{\def\x{do c}}
+ % default{\def\x{no match}}
+\fi
+\skvifcasse{x}
+ case{a}{\def\x{do a}}
+ case{b}{\def\x{do b}}
+ case{c}{\def\x{do c}}
+\elsedo
+ \def\x{no match}
+\endif
+
+\skvifcasse{x}
+ case{a}{\def\x{do a}}
+ case{b}{\def\x{do b}}
+ case{c}{\def\x{do c}}
+%\elsedo
+% \def\x{no match}
+\endif
+
+%++++++++++++ Processing a key's value as a comma list +++++++++++%
+
+\skvordkeys[KV]{fam}{key1,key2}[default]{%
+ .arg{#1/#2}%
+ \def\x##1{##1*#1*#2}%
+}
+\def\aval{val1a/val1b}
+\def\bval{val2a/val2b,val2c/val2d}
+\skvsetkeys[KV]{fam}{%
+ key1=\aval,
+ key2=.eprocess list{\bval}
+}
+
+\skvordkeys[KV]{fam}{key1}[default]{\def\x##1{##1*#1}}
+\def\aval{val1a,val1b,val1c,val1d}
+\def\bval{\aval}
+\def\cval{\bval}
+\skvsetkeys[KV]{fam}{%
+ key1=.expand once process list{\aval},
+ key1=.expand twice process list{\bval},
+ key1=.expand process list{\cval}
+}
+
+% End of file skeyval-pokayoke1.tex
diff --git a/Master/texmf-dist/doc/latex/skeyval/skeyval-pokayoke2.pdf b/Master/texmf-dist/doc/latex/skeyval/skeyval-pokayoke2.pdf
index 7e995aab364..8f1cda84161 100644
--- a/Master/texmf-dist/doc/latex/skeyval/skeyval-pokayoke2.pdf
+++ b/Master/texmf-dist/doc/latex/skeyval/skeyval-pokayoke2.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/skeyval/skeyval-pokayoke2.tex b/Master/texmf-dist/doc/latex/skeyval/skeyval-pokayoke2.tex
index 57195061611..b720169ebbe 100644
--- a/Master/texmf-dist/doc/latex/skeyval/skeyval-pokayoke2.tex
+++ b/Master/texmf-dist/doc/latex/skeyval/skeyval-pokayoke2.tex
@@ -1,8 +1,6 @@
\documentclass[
insertwatermark,watermarkcolor=blue!55,
- firstpagenumber=2,
- maketitlepage,
- unknown-key
+ firstpagenumber=2,maketitlepage,unknown-option
]{skeyval-testclass}
\setupskvtestclass{%
@@ -88,7 +86,7 @@
count in=\xc all \x satisfying \ifnum\x>5\fi
] in \alist {
\newforeach[
- parser={;},
+ parser={;}, subparser=:,
evaluate=\y as \ye using \numexpr\y*10
]
\y:\z in {1:red; 2:green; 3:blue; 4:brown; 5:purple} do {
@@ -103,4 +101,64 @@
\end{document}
-% End of file skeyval-pokayoke2.tex \ No newline at end of file
+
+%++ Pokayoke for \skvsetdirectkeysparser and \skvsetdefinekeysparser ++%
+
+\usepackage{tikz}
+\usetikzlibrary{shapes.geometric}
+\makeatletter
+\skvsetdirectkeysparser{;}
+\skvsetdefinekeysparser{;}
+\directkeys*{
+ .family=graph;
+ .holder prefix=cvt@;
+ .initialize keys after define;
+ .define keys={
+ .ord/num vertices,number of vertices,vertices/6/
+ \skvensureinteger{vertices}{#1}
+ \def\cvt@vertices{#1}
+ ;
+ .ord/radius,circle radius/2/\def\cvt@radius{#1};
+ .cmd/x,y/0
+ };
+ .preset keys={vertices,radius,x,y}
+}
+\newcommand*\drawgraph[1][]{%
+ \directkeys{
+ .family=graph;
+ .set keys={#1}
+ }
+ \pgfmathsetmacro\halfcircleradius{\cvt@radius/2}
+ \draw[blue] (\cvt@x,\cvt@y) circle (\halfcircleradius cm)
+ node [regular polygon, regular polygon sides=\cvt@vertices,
+ minimum size=\cvt@radius cm, draw=none, name={vertex set}]{};
+ \foreach \x in {1,...,\cvt@vertices}{
+ \node[draw,circle,inner sep=1pt,blue,fill=blue] at (vertex set.corner \x){};
+ }
+ \foreach \x in {1,...,\cvt@vertices}{
+ \foreach \y in {\x,...,\cvt@vertices}{
+ \draw[ultra thin, red] (vertex set.corner \x)--(vertex set.corner \y);
+ }
+ }
+}
+\makeatother
+\begin{document}
+\begin{tikzpicture}
+\drawgraph[number of vertices=6, circle radius=3, x=0, y=0]
+\drawgraph[number of vertices=8, circle radius=3, x=4, y=0]
+\end{tikzpicture}
+\par\bigskip
+\begin{tikzpicture}
+% Use default values of positions:
+\drawgraph[vertices=8, radius=3]
+% Use default values of vertices and radius:
+\drawgraph[x=4, y=0]
+\end{tikzpicture}
+\par\bigskip
+\begin{tikzpicture}
+% Use default values of all keys:
+\drawgraph
+\end{tikzpicture}
+\end{document}
+
+% End of file skeyval-pokayoke2.tex
diff --git a/Master/texmf-dist/doc/latex/skeyval/skeyval-testclass.cls b/Master/texmf-dist/doc/latex/skeyval/skeyval-testclass.cls
index c81c535c0ef..ecb846dc99b 100644
--- a/Master/texmf-dist/doc/latex/skeyval/skeyval-testclass.cls
+++ b/Master/texmf-dist/doc/latex/skeyval/skeyval-testclass.cls
@@ -1,5 +1,5 @@
%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
-% This is file 'skeyval-testclass.cls', version 1.1a, 2012/10/16. %
+% This is file 'skeyval-testclass.cls', version 1.2, 2013/02/10. %
% %
% This package and accompanying files may be distributed and/or %
% modified under the conditions of the LaTeX Project Public License, %
@@ -23,11 +23,10 @@
% skeyval-pstkey.sty, skeyval-pstkey.tex, skeyval-testclass.cls, %
% and skeyval-testpkg.sty. %
% %
-% Copyright (c) 2010-2012 Ahmed Musa (amusa22@gmail.com). %
+% Copyright (c) 2010-2013 Ahmed Musa (amusa22@gmail.com). %
%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
-\ProvidesClass{skeyval-testclass}
- [2012/10/16 v1.1a skeyval test class (AM)]
+\ProvidesClass{skeyval-testclass}[2013/02/10 v1.2 skeyval test class (AM)]
\NeedsTeXFormat{LaTeX2e}[2011/06/27]
\@ifpackageloaded{skeyval}{}{\RequirePackage{skeyval}}
\@ifpackageloaded{xcolor}{}{\RequirePackage{xcolor}}
@@ -80,9 +79,7 @@
\skvnewlet\skv@sav@footnote\footnote
\skvnewlet\skv@sav@thanks\thanks
\AtEndOfPackage{%
- \skvdisablekeys[SKVC]{title}{%
- insertwatermark
- }%
+ \skvdisablekeys[SKVC]{title}{insertwatermark}%
}
\AtBeginDocument{%
\def\footnote{\unskip\skv@sav@footnote}%
@@ -94,6 +91,11 @@
}
\let\skvcl@settitlepageno\@gobble
+% Example of option and nonoption keys:
+\skvordkeys[KV]{fam}{testkey1,testkey2}[value]{}
+\skvoptionkeys[KV]{fam}{testkey1}
+\skvnonoptionkeys[KV]{fam}{testkey2}
+
% LaTeX will zap spaces in key name, anyway. So our options don't have
% spaces within themselves.
@@ -107,6 +109,8 @@
.family=textemphasis,
.hp=xem@,
.new options={
+ .initialize keys after define,
+ .ord/{testkey1,testkey2,testkey3}/default,
.bool/useitalic/true,
.bool/usebold/true,
.bool/usecolor/true,
@@ -127,6 +131,8 @@
usecolour/usecolor,
colour/color,
},
+ .option keys = {testkey1},
+ .nonoption keys = {testkey2,testkey3},
% Modifying the article title:
.change family=title,
.hp=skvcl@,
@@ -183,32 +189,29 @@
.cmd/watermarkscale/5,
.cmd/watermarkcolor/gray!55,
},
- .styles={
+ .slots={
showdate/putdate=#1,
first-page-number/firstpagenumber=#1,
titlepage/maketitlepage=#1,
},
- % Options execution and processing:
- .families = {textemphasis,title},
- % Ececute the options in all the prevailing families. If any of
- % the options isn't found in at least one family, report error (ie,
- % don't save the key to the list of 'remaining keys'). Unknown options
- % should be flagged immediately.
- .execute options+={
- useitalic,usebold,usecolor,color,
- make-textemphasis-inactive=false,putdate,datefont,
- clearpage=false,pretitleskip,posttitleskip,
+ % Ececute the options in the current family. If any of the options
+ % isn't found, report error (ie, don't save the key to the list of
+ % 'remaining keys'). Unknown options should be flagged immediately.
+ % Use '.execute options+' or '.execute options in all families' to
+ % execute options in multiple families.
+ .execute options={
+ putdate,datefont,clearpage=false,pretitleskip,posttitleskip,
authorfont,titlefont,watermarkscale,firstpagenumber,
insertwatermark=false,watermarkxshift,watermarkyshift,
watermarktext,watermarkcolor,fontsize
},
- % Use '.mega process options*' or '.copy class options and process...':
-% .mega process options*={
-% prefix=SKVC,
-% families={textemphasis,title},
-% },
- .copy class options and process options in all families,
+ .families={textemphasis,title},
+ .process options in all families,
}
+%\show\skvcurrentpoxkeys
+
+% testkey1 is an option key: don't set it outside option list:
+% \skvsetkeys[SKVC]{textemphasis}{testkey1}
\skvrobustdef*\setupskvtestclass{%
\skvsetkeys*+[SKVC]{textemphasis,title}%
diff --git a/Master/texmf-dist/doc/latex/skeyval/skeyval-testpkg.sty b/Master/texmf-dist/doc/latex/skeyval/skeyval-testpkg.sty
index 30de37acd89..d2467bc9f1d 100644
--- a/Master/texmf-dist/doc/latex/skeyval/skeyval-testpkg.sty
+++ b/Master/texmf-dist/doc/latex/skeyval/skeyval-testpkg.sty
@@ -1,5 +1,5 @@
%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
-% This is file 'skeyval-testpkg.sty', version 1.1a, 2012/10/16. %
+% This is file 'skeyval-testpkg.sty', version 1.2, 2013/02/10. %
% %
% This package and accompanying files may be distributed and/or %
% modified under the conditions of the LaTeX Project Public License, %
@@ -23,11 +23,10 @@
% skeyval-pstkey.sty, skeyval-pstkey.tex, skeyval-testclass.cls, %
% and skeyval-testpkg.sty. %
% %
-% Copyright (c) 2010-2012 Ahmed Musa (amusa22@gmail.com). %
+% Copyright (c) 2010-2013 Ahmed Musa (amusa22@gmail.com). %
%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
-\ProvidesPackage{skeyval-testpkg}
- [2012/10/16 v1.1a skeyval test package 1 (AM)]
+\ProvidesPackage{skeyval-testpkg}[2013/02/10 v1.2 skeyval test package (AM)]
\NeedsTeXFormat{LaTeX2e}
\@ifpackageloaded{skeyval}{}{\RequirePackage{skeyval}}
\RequirePackage{graphicx}
@@ -41,7 +40,7 @@
% Declare options with default values that will be used when the options
% are called without user values.
%
-\skvDeclarePassedOptionsLoadPackage[SKVT]{testpkg}{%
+\skvdeclarepassedoptionsloadpackage[SKVT]{testpkg}{%
hyperref={colorlinks,breaklinks},xcolor=svgnames
}
@@ -72,8 +71,10 @@
\def\alignvalb{\alignval}
\def\stextstyle{\sffamily}
-\skvsetkeys[SKVT]{abrtext}{align=.expand twice{\alignvalb},
- text style=.expand once{\stextstyle},author,show author}
+\skvsetkeys[SKVT]{abrtext}{
+ align=.expand twice{\alignvalb},
+ text style=.expand once{\stextstyle},author,show author
+}
%%+++++++++++++++++++++++++++ Citations +++++++++++++++++++++++++++%%
@@ -266,13 +267,12 @@
.k handler={2}{\def\x##1{##1*#1*#2}},
.l handler={3}{\def\x##1{##1*#1*#2*#3}}
},
+ .reserve handlers={reservedx , reservedy},
.holder prefix = mp@,
.prefix = KV,
- .add prefixes = {KVA,KVD},
.families = {fam1, fam2},
.add family = {fam3},
.add families = {fama,famb,famc},
- .ignore prefixes = {KVA,KVD},
.ignore families = {fama,famb,famc},
.restore families = {fama,famb},
.restore paths = {KVA/fama,KVD/famc},
@@ -330,21 +330,21 @@
.set keys = {keya=vala},
},
.exec code = \def\keycval{true},
- % Prepend style keye to key1 and key2:
- .prepend style={key1/{keye=.expanded{\keycval}},key2/{keye=false}},
- % Multi-prepend styles:
- .prepend style={{key3,key4}/{keye=true,keyf=true},key5/{keye=false}},
- % Prepend style keyd to key6:
- .prepend style={key6/{keyd=right}},
- % Append styles keye and keyf to key7 and key8.
- % '.styles' and '.style' are equivalent to '.append styles'
- % and '.append style'.
- .append style={key7/{keye=true},key8/{keyf=false}},
+ % Prepend slot keye to key1 and key2:
+ .prepend slot={key1/{keye=.expanded{\keycval}},key2/{keye=false}},
+ % Multi-prepend slots:
+ .prepend slot={{key3,key4}/{keye=true,keyf=true},key5/{keye=false}},
+ % Prepend slot keyd to key6:
+ .prepend slot={key6/{keyd=right}},
+ % Append slots keye and keyf to key7 and key8.
+ % '.slots' and '.slot' are equivalent to '.append slots'
+ % and '.append slot'.
+ .append slot={key7/{keye=true},key8/{keyf=false}},
% The next two link keyb and keyc to key9. #1 here refers to the
% current value of key9. The same effect can be achieved directly
% via the '.link' handler:
- .prepend style={key9/{keyb=#1}},
- .append style={key9/{keyc=#1}},
+ .prepend slot={key9/{keyb=#1}},
+ .append slot={key9/{keyc=#1}},
.set keys = {key9=val9},
% Link keye and keyf to key10 and key11. The values of key10 and
% key11 are used to set keye and keyf. key10 and key11 are hence
@@ -432,4 +432,23 @@
\skvprocessoptions*+[SKVT]<abrtext,shadowbox,citation,testpkg>\relax
%\skvrestrictedprocessoptions*+[SKVT]<abrtext,shadowbox,citation,testpkg>\relax
+\skvcomment
+Here you could also use:
+
+\directkeys{
+ .mega process options*={
+ .prefix=SKVT,
+ .families={abrtext,shadowbox,citation,testpkg},
+ }
+}
+
+or
+
+\directkeys{
+ .prefix=SKVT,
+ .families={abrtext,shadowbox,citation,testpkg},
+ .copy class options and process options in all families,
+}
+\endcomment
+
\endinput
diff --git a/Master/texmf-dist/doc/latex/skeyval/skeyval-view-pokayoke1.pdf b/Master/texmf-dist/doc/latex/skeyval/skeyval-view-pokayoke1.pdf
deleted file mode 100644
index fc4c8014215..00000000000
--- a/Master/texmf-dist/doc/latex/skeyval/skeyval-view-pokayoke1.pdf
+++ /dev/null
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/skeyval/skeyval-view-pokayoke1.tex b/Master/texmf-dist/doc/latex/skeyval/skeyval-view-pokayoke1.tex
deleted file mode 100644
index 9ad80b2a5c5..00000000000
--- a/Master/texmf-dist/doc/latex/skeyval/skeyval-view-pokayoke1.tex
+++ /dev/null
@@ -1,139 +0,0 @@
-\documentclass{skeyval-testclass}
-\usepackage[xcolor-options=dvipsnames]{skeyval-view}
-\usetikzlibrary[topaths]
-
-\makeatletter
-
-\setupviewkeys{length of default=30}
-
-\skvdefinekeys[KV]{fam1}[vhp@]{%
- .initialize after define,
- .ord/{keya,keya2}/default-a,
- .cmd/keyb,
- .zcmd/key c/\def\cmdc##1{##1}/
- \edef\y{\detokenize\expandafter{\vhp@keyc}}\def\x##1{#1*key c*##1},
- % No default for keyd:
- .choice/keyd/.na
- /{center.do=\def\x##1{#1*##1},left.do={\def\ans{#1}},right}
- /\def\z##1{#1*##1}
- /\@warning{Invalid value for keyd},
- .bool/show shadow/true,
- .zbool/show center/true/\edef\cmd{\ifvhp@showcenter Yes\else No\fi},
- .ord/keye,
- .cmd/keyf,
-}
-%\show\y
-%\skvshowcs{KV@fam1@show center}
-%\show\cmd
-
-% Define some keys:
-\directkeys*{
- .prefix=KV,
- .family=fam2,
- .holder prefix=hp@,
- .initialize keys after define,
- .define keys={%
- .ord/keya,
- .ord/galaxy/Messier 51a/\def\constellation{Canes Venatici},
- .choice/planet/Earth/{Earth.do=\def\x##1{#1*##1},Mars,Jupiter},
- .bool/space travel/true,
- .cmd/astronaut/Yuri Gagarin/
- \edef\x{\ifx\hp@astronaut\@empty Neil Armstrong\else\hp@astronaut\fi},
- .ord/space observatory/Hubble Space Telescope/
- \def\father{Lyman Spitzer~(1914--1997)},
- },
-}
-
-\makeatother
-
-\begin{document}
-
-\title{The \texttt{\textcolor{blue}{skeyval-view}} Package\\[.25ex]
- Version 1.1a\\[1ex]
- \textsf{Test document}}
-\author{Ahmed Musa}
-\maketitle
-
-\skvviewkeys{%
- .show={
- family=fam1,
- color=blue
- },
- .show={
- families={fam1,fam2},
- only those with default=true,
- write to file=\jobname.skvv,
- show labels=true,
- show wlabels=true,
- },
- .show={
- family=fam1,
- only those with default=[none],
- show labels=true,
- color=cyan,
- },
- .show={
- families={fam1,fam2},
- only those without default=true,
- color=purple,
- },
- .show={
- family=fam2,
- columns={prefix,family,key type,default},
- color=teal
- },
- .show={
- only those in family=fam2,
- columns={family,type,default}
- },
- .show={
- only those in families={fam1,fam2},
- columns={prefix,family,type,default},
- color=magenta
- }
-}
-
-\newpage
-
-\skvtestcnt0\relax
-\skvrecurse
- \advance\skvtestcnt1\relax
- \vskip\baselineskip\noindent
- \textcolor{blue!\the\numexpr10*\skvtestcnt!red!%
- \the\numexpr100/\skvtestcnt}{%
- The play was a great success, but the audience was a disaster.
- \endgraf{\small Oscar Wilde, 1854--1900}
- }%
-\while
- \ifnum\skvtestcnt<8\relax
-\fi
-
-% Credit: Quintin Jean-Noël
-\newcount\mycount
-\begin{center}
-\begin{tikzpicture}[scale=.5,transform shape]
-\newforeach \nr in {1,...,8}{
- \mycount=\numexpr(\nr-1)*45\relax
- \node[draw,circle,inner sep=0.25cm] (N-\nr) at (\the\mycount:5.4cm) {};
-}
-\newforeach \nr in {9,...,16}{
- \mycount=\numexpr(\nr-1)*45+22\relax
- \node[draw,circle,inner sep=0.25cm] (N-\nr) at (\the\mycount:5.4cm) {};
-}
-\newforeach \nr in {1,...,15}{
- \mycount=\numexpr\nr+1\relax
- \newforeach \nra in {\the\mycount,...,16}{
- \path (N-\nr) edge[->,bend right=3] (N-\nra) edge[<-,bend left=3]
- (N-\nra);
- }
-}
-\end{tikzpicture}
-\end{center}
-
-
-\bigskip
-Find more information about the \textcolor{red}{\texttt{show shadow}} option on page~\pageref{KV/fam1/show shadow}.
-
-\end{document}
-
-% End of file skeyval-view-pokayoke1.tex \ No newline at end of file
diff --git a/Master/texmf-dist/tex/latex/skeyval/skeyval-bc.sty b/Master/texmf-dist/tex/latex/skeyval/skeyval-bc.sty
index de53f5161e0..0e468a36db6 100644
--- a/Master/texmf-dist/tex/latex/skeyval/skeyval-bc.sty
+++ b/Master/texmf-dist/tex/latex/skeyval/skeyval-bc.sty
@@ -1,7 +1,8 @@
%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
% This is file 'skeyval-bc.sty', version 0.73 of skeyval package, %
-% January 2011. %
+% 2011/01/01. %
% NOTE %
+% %
% This file is provided only for backward compatibility (bc) of the %
% skeyval package. Beginning from version 1.0, September 2012, the %
% package has changed radically. Users of pre-version 1.0 of the package %
@@ -85,7 +86,7 @@
\SKV@setcode{126}{13}% ~
\def\SKV@rcsid$#1: #2 #3 #4 #5${#4 v#3}
\ProvidesPackage{skeyval}[%
- \SKV@rcsid $Id: skeyval.sty,v 0.72 2010/05/21 09:00:00 Ahmed Musa $
+ \SKV@rcsid $Id: skeyval.sty,v 0.73 2011/01/01 09:00:00 Ahmed Musa $
Extensions to the xkeyval parser (AM)
]
\NeedsTeXFormat{LaTeX2e}[1996/12/01]
diff --git a/Master/texmf-dist/tex/latex/skeyval/skeyval-core.tex b/Master/texmf-dist/tex/latex/skeyval/skeyval-core.tex
index 83348e842a8..709b36b5496 100644
--- a/Master/texmf-dist/tex/latex/skeyval/skeyval-core.tex
+++ b/Master/texmf-dist/tex/latex/skeyval/skeyval-core.tex
@@ -1,5 +1,5 @@
%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
-% This is file 'skeyval-core.tex', version 1.1a, 2012/10/16. %
+% This is file 'skeyval-core.tex', version 1.2, 2013/02/10. %
% %
% This package and accompanying files may be distributed and/or %
% modified under the conditions of the LaTeX Project Public License, %
@@ -23,7 +23,7 @@
% skeyval-pstkey.sty, skeyval-pstkey.tex, skeyval-testclass.cls, %
% and skeyval-testpkg.sty. %
% %
-% Copyright (c) 2010-2012 Ahmed Musa (amusa22@gmail.com). %
+% Copyright (c) 2010-2013 Ahmed Musa (amusa22@gmail.com). %
%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
\csname skeyval-core-loaded\endcsname
@@ -75,26 +75,25 @@
\newdimen\skvz@\skvz@=0pt\relax
\newcount\skvm@ne\skvm@ne=-1\relax
\ifcase
- \ifx\eTeXversion\@undefined0\else
- \ifnum\eTeXversion<\tw@0\else1\fi\fi\relax
+ \ifx\eTeXversion\@undefined 0\else
+ \ifnum\eTeXversion<\tw@ 0\else 1\fi
+ \fi\relax
\errhelp{This package requires eTeX version 2 or higher.}
\errmessage{skeyval package: eTeX not loaded or old version.}
\expandafter\endinput
\fi
-%\chardef\skv@five=5\relax
-%\chardef\skv@six=6\relax
\newif\ifskv@latex
\newif\ifskv@tempst
\ifx\ProvidesFile\@undefined
\skv@latexfalse
- \message{File 'skeyval-core.tex' 2012/10/16 v1.1a:
+ \message{File 'skeyval-core.tex' 2013/02/10 v1.2:
Core of 'skeyval' key-value parser (AM)}
\input skeyval-ltxcmds
\else
\skv@latextrue
\ProvidesFile{skeyval-core.tex}
- [2012/10/16 v1.1a Base file of skeyval package (AM)]
+ [2013/02/10 v1.2 Base file of skeyval package (AM)]
\@addtofilelist{skeyval-core.tex}
\long\def\@nodocument#1{%
\@latex@error{'#1' appeared\on@line\space without
@@ -105,12 +104,19 @@
% skeyval-ltxcmds.tex defines \PackageError, etc:
\protected\def\skv@warn{\PackageWarningNoLine{skeyval}}
\protected\def\skv@err{\PackageError{skeyval}}
-
+% No \protected for \skv@ehd:
+\def\skv@ehd{%
+ I have encountered a problem here. Try typing <return>
+ \MessageBreak to proceed. If that doesn't work, type X then
+ <return>\MessageBreak to quit.
+}
+\let\skvgenericexception\@latexerr
\protected\def\skvtracingall{%
\tracinggroups\@ne\tracingifs\@ne\loggingall\tracingassigns\@ne
}
\let\skvloggingall\skvtracingall
-
+\long\def\skviofii#1#2{#1}
+\long\def\skviiofii#1#2{#2}
% A \relax'ed command should not be redefined, because we don't know
% if it is temporarily or permanently made \relax.
\long\def\skvifdefinable#1#2{%
@@ -119,28 +125,81 @@
\else
\expandafter\@secondoftwo
\fi
- {\@latex@error{Command '\string#1' already defined}\@ehd}
+ {\@latex@error{Command '\string#1' already defined}\skv@ehd}
{#2}%
}
-
% \skvgenloop{<parser>}{<list>}{<1.parameter.callback>}
-% The parser may be empty. This is the case for nsv/tsv lists.
-\def\skvgenloop#1#2#3{%
+%
+% 1. The parser may be empty. This is the case for nsv/tsv lists.
+% 2. The normalization of the list, including dealing with active parsers,
+% is left to the caller.
+% 3. \@iden will help remove spurious leading spaces.
+%
+\protected\def\skvgenloop#1#2#3{%
\def\skv@gendo##1#1{%
\ifx\skv@gendo##1\expandafter\@gobble\else\expandafter\@iden\fi
- {#3\skv@gendo}%
+ {#3\expandafter\skv@gendo\@iden}%
+ }%
+ \expandafter\skv@gendo\@iden#2#1\skv@gendo#1%
+}
+% \skvrescan{<macro>}
+\protected\def\skvrescan#1{%
+ \begingroup
+ \endlinechar\m@ne\newlinechar\m@ne
+ \catcode`\@=11\relax
+ \everyeof{\skv@rescan@guard}%
+ \def\reserved@a##1\skv@rescan@guard{%
+ \endgroup
+ \edef#1{\unexpanded\expandafter{\@gobble##1}}%
+ }%
+ % \relax protects any blank space leading the content of #1:
+ \expandafter\reserved@a\scantokens\expandafter{\expandafter\relax#1}%
+}
+
+% Process a comma list with a simple callback. This can't be used if #2
+% isn't scannable or if scanning #2 will change the signature of
+% its token list.
+%
+% \skv@commaact{<list>}{<1.parameter.callback>}
+%
+% Example:
+%
+% \def\emptify{\skv@commaact{\def##1{}}}
+%
+\begingroup
+\catcode`\,=\active
+\protected\gdef\skv@commaact#1#2{%
+ \begingroup
+ \toks@{}%
+ \def,##1{%
+ \ifx\skv@commaact##1\else
+ \ifx,##1%
+ % Double comma seen:
+ \expandafter\expandafter\expandafter,%
+ \else
+ \toks@\expandafter{\the\toks@#2}%
+ \fi
+ \fi
}%
- \skv@gendo#2#1\skv@gendo#1%
+ \begingroup
+ \edef\skv@tempa{\unexpanded{,#1}}%
+ \catcode`\,=\active
+ \skvrescan\skv@tempa
+ % Add a trailing \skv@commaact, in case the list is ended by a comma (,):
+ \expandafter\endgroup\skv@tempa,\skv@commaact
+ \expandafter\endgroup\the\toks@
}
-\def\skvnewregister#1#2{%
+\endgroup
+
+\protected\def\skvnewregister#1#2{%
\def\skv@prova{#1}%
\def\skv@provb{\bool}%
- % We don't want to expose \if:
+ % We don't want to expose \if while in the next conditional:
\def\skv@provc{\if}%
\ifx\skv@prova\skv@provb
\let\skv@prova\skv@provc
\fi
- \skvgenloop{}{#2}{%
+ \skv@commaact{#2}{%
\skvifdefinable##1{%
\csname new\expandafter\expandafter\expandafter\@gobble
\expandafter\string\skv@prova\endcsname##1%
@@ -148,13 +207,7 @@
}%
}
\let\skvnewregisters\skvnewregister
-
-\skvnewregisters\toks{\skv@toksa\skv@toksb}
-
-% \skvletmanytocmd{<nsv.cmdlist>}{<cmd>}
-\long\def\skvletmanytocmd#1#2{%
- \skvgenloop{}{#1}{\let##1= #2}%
-}
+\skvnewregisters\toks{\skv@toksa,\skv@toksb}
% Sometimes we change \bgroup temporarily to avoid \futurelet confusing
% it with explicit \bgroup character. The change does confuse \skvifnextchar
@@ -162,36 +215,50 @@
% in \skvifnextchar:
\let\skv@orig@bgroup\bgroup
+\def\reserved@a#1{%
+ \def\skvifnextisouter{%
+ \expandafter\skv@ifnextisouter\meaning\skv@nextseen#1\relax
+ }%
+ \def\skv@ifnextisouter##1#1##2\relax{%
+ \ifcat$##2$\expandafter\@secondoftwo\else\expandafter\@firstoftwo\fi
+ }%
+}
+\expandafter\reserved@a\expandafter{\detokenize{outer macro}:}
+
% We modify LaTeX kernel's \@ifnextchar to eliminate the need for
-% doubling the hash character in #2 or #3. \@nextseen may be needed
+% doubling the hash character in #2 or #3. \skv@nextseen may be needed
% outside the group; so we use \global.
\long\def\skvsimpleifnextchar#1#2#3{%
\begingroup
\let\reserved@d=#1%
\edef\reserved@a{\endgroup\unexpanded{#2}}%
\edef\reserved@b{\endgroup\unexpanded{#3}}%
- \global\futurelet\@nextseen\skv@simpleifnext
+ \global\futurelet\skv@nextseen\skv@simpleifnext
}
\def\skv@simpleifnext{%
- \ifx\@nextseen\@sptoken
- % Experience shows that this \skv@ifnextdo must be unique: If we were
- % to use \next or some other generic command, it might have been
- % let to \if or \fi before being assigned here and will confuse
- % the above \ifx:
- \let\skv@ifnextdo\skv@simpleifn@xt
+ \ifx\skv@nextseen\@sptoken
+ \let\skv@letnext\skv@simpleifn@xt
\else
- \ifx\@nextseen\reserved@d
- \let\skv@ifnextdo\reserved@a
+ \ifx\skv@nextseen\reserved@d
+ \let\skv@letnext\reserved@a
\else
- \let\skv@ifnextdo\reserved@b
+ \let\skv@letnext\reserved@b
\fi
\fi
- \skv@ifnextdo
+ \skv@letnext
}
\lowercase{\def\skv@simpleifn@xt} {%
- \global\futurelet\@nextseen\skv@simpleifnext
+ \global\futurelet\skv@nextseen\skv@simpleifnext
}
-\long\protected\def\skvifnextchar#1#2#3{%
+
+% Tests for \skvifnextchar:
+%
+% \outer\def\foo{}
+% \iftrue\skvifnextchar*\relax\relax\foo\fi
+% \iftrue\skvifnextchar*\relax\relax\fi
+% \skvifnextchar*\relax\relax\iftrue\fi
+%
+\protected\long\def\skvifnextchar#1#2#3{%
\skvsimpleifnextchar\skv@orig@bgroup{%
\skvsimpleifnextchar{#1}{#2}{#3}%
}{%
@@ -200,7 +267,11 @@
\skvsimpleifnextchar\egroup{%
\skvsimpleifnextchar{#1}{#2}{#3}%
}{%
- \skv@ifnextchar@a{#1}{#2}{#3}
+ \skvifnextisouter{%
+ \skvsimpleifnextchar{#1}{#2}{#3}%
+ }{%
+ \skv@ifnextchar@a{#1}{#2}{#3}%
+ }%
}%
}%
}
@@ -224,6 +295,14 @@
\fi
{#1}{\unexpanded{#3}}%
}
+\let\skv@sav@ifnextchar\skvifnextchar
+\protected\def\skvusesimpleifnextchar{%
+ \let\skvifnextchar\skvsimpleifnextchar
+}
+\let\skvuselatexifnextchar\skvusesimpleifnextchar
+\protected\def\skvuserobustifnextchar{%
+ \let\skvifnextchar\skv@sav@ifnextchar
+}
% Expandable \@testopt:
%
@@ -267,11 +346,12 @@
\skvifstar{\let\l@ngrel@x\relax#1}{\let\l@ngrel@x\long#1}%
}
\long\protected\def\skv@testopt#1#2{\skvifnextchar[{#1}{#1[{#2}]}}
+\long\protected\def\skv@testpnopt#1#2{\skvifnextchar({#1}{#1({#2})}}
\long\protected\def\skvifstar#1{\skvifnextchar*{\@firstoftwo{#1}}}
\def\skv@def@#1#2#3{%
\ifdefined#3%
\ifx#3\relax\else
- \skv@err{Command \detokenize{#3} already exists}\@ehd
+ \skv@err{Command \detokenize{#3} already exists}\skv@ehd
\fi
\fi
\ifcat$\detokenize{#2}$\else
@@ -293,6 +373,7 @@
\skvrobustdef*\skvrobustredef{\skvstarorlong{\skv@redef@{}{p}}}
\skvrobustdef*\skvrobustgdef{\skvstarorlong{\skv@def@{g}{p}}}
\skvrobustdef*\skvnewdef{\skvstarorlong{\skv@def@{}{}}}
+\skvrobustdef*\skvrenewdef{\skvstarorlong{\skv@redef@{}{}}}
\skvrobustdef*\skvnewedef{\skvstarorlong{\skv@def@{e}{}}}
\skvrobustdef*\skvnewgdef{\skvstarorlong{\skv@def@{g}{}}}
\skvrobustdef*\skvrobustcsdef{\skvstarorlong{\skv@csdef@{}{p}}}
@@ -305,10 +386,17 @@
}
\skvrobustdef*\skvcomment{%
\begingroup
- \catcode`\{=12 \catcode`\}=12 \catcode`\#=12\relax
- \skv@c@mment
+ \def\do##1{\catcode`##1=12\relax}%
+ \dospecials
+ \skv@endcomment
}
-\skvrobustdef\skv@c@mment#1\endcomment{\endgroup}
+\begingroup
+\catcode`\!=0
+\catcode`\\=12
+!long!gdef!skv@endcomment#1\endcomment{!endgroup}
+!endgroup
+%\skvrobustdef\skv@c@mment#1\endcomment{\endgroup}
+
\skvnewedef*\skv@hashchar{\string#}
\let\nofilter\relax
% Don't use '=' at the end of the following definition; the user
@@ -328,6 +416,7 @@
\skvnewdef\skv@gobbletoend#1\skv@gobble@nil{}
\skvnewlet\skv@gobble@nil\relax
\def\@space{ }
+\let\then\iffalse
\skvnewdef\skvswap#1#2{#2#1}
\skvnewdef*\skv@quark{\@gobble\skv@quark}
\skvnewlet\skvrom\romannumeral
@@ -339,9 +428,12 @@
\skvnewdef\skvafterelsei#1\else#2\fi{\fi#1}
\skvnewlet\skvafterelse\skvafterelsei
\skvnewdef\skvafterelseii#1\else#2\fi{\fi#2}
-\skvnewedef*\skv@simplearg{\unexpanded{#1}}
-
-\long\def\skv@in@#1#2{%
+\skvnewdef*\skv@simplearg{##1}
+\skvnewlet\skvsanitizemacro\@onelevel@sanitize
+\skvrobustdef*\skv@usetempst#1#2{%
+ \edef#2{\skvifdefboolTF{skv@tempst}\skvexpandonce\unexpanded{#1}}%
+}
+\skvrobustdef*\skvtestifin#1#2{%
\begingroup
\long\def\in@@##1#1##2\in@@{%
\edef\in@@{\unexpanded{##2}}%
@@ -352,7 +444,7 @@
}
\skvrobustdef*\skvcsnewif#1{%
\skvifstrcmpTF{#1}{x}{%
- \skv@err{Redefining primitve '\@backslashchar ifx'?}\@ehd
+ \skv@err{Redefining primitve '\@backslashchar ifx'?}\skv@ehd
}{%
\csname newif\expandafter\endcsname\csname if#1\endcsname
}%
@@ -376,8 +468,8 @@
\edef#2{.#1}%
\edef#2{\expandafter\skv@zapspaces#2 \zap@nil}%
}
-
-\newcommand\skvifleadspace[3]{%
+% \skvifleadspaceTF{<toks>}{<true>}{<false>}
+\newcommand\skvifleadspaceTF[3]{%
\romannumeral\csname
@\skvifnullTF{#1}{second}{\iffalse{\fi\skv@ifleadspace.#1 x}}%
oftwo\endcsname{0 #2}{0 #3}%
@@ -387,6 +479,8 @@
\expandafter\@gobble\expandafter{\iffalse}\fi
}
+% \skvifldspaceTF is faster than \skvifleadspaceTF.
+%
% \skvifldspaceTF{ }{}{} gives <true> as desired.
\begingroup
\lccode`\&=0 \catcode`\&=7 \lccode`\!=0 \catcode`\!=8
@@ -406,7 +500,10 @@
}%
}
}
-
+\skvnewdef\skvotrimspace{\expandafter\skvtrimspace\expandafter}
+\skvnewdef\skvxtrimspace#1{%
+ \expandafter\skvtrimspace\expandafter{\romannumeral-`\q#1}%
+}
\skvrobustdef*\skvdespace#1#2{\edef#2{\skvtrimspace{#1}}}
\skvrobustdef*\skvdespacecontent#1{%
\edef#1{\expandafter\skvtrimspace\expandafter{#1}}%
@@ -429,16 +526,14 @@
% \skvifcsname x\then\def\x{T}\else\def\x{F}\fi
\skvnewdef*\skvifcsname#1\then{\if0\skvifcsdefTF{#1}{0}{1}}
\skvnewdef*\skvifdefTF#1{%
- \skvifblankTF{#1}\@secondoftwo{%
- \skvifxTF#1\@undefined{%
- \@secondoftwo
- }{%
- \ifx\relax#1%
- \expandafter\@secondoftwo
- \else
- \expandafter\@firstoftwo
- \fi
- }%
+ \skvifxTF{#1}\skv@undefined{%
+ \@secondoftwo
+ }{%
+ \ifx\relax#1%
+ \expandafter\@secondoftwo
+ \else
+ \expandafter\@firstoftwo
+ \fi
}%
}
\skvnewdef*\skvifdefFT#1{\skvifdefTF{#1}\@secondoftwo\@firstoftwo}
@@ -461,8 +556,21 @@
}%
}
\skvnewdef*\skvifcsdefFT#1{\skvifcsdefTF{#1}\@secondoftwo\@firstoftwo}
-\def\skv@ifx@#1#2\skv@ifx@nil{\expandafter#1}
-\def\skv@ifx@@#1#2\skv@ifx@nil{#1}
+% Don't check for blank #1. For internal use:
+\skvnewdef*\skvifnamedefTF#1{%
+ \ifcsname#1\endcsname
+ \expandafter\ifx\csname#1\endcsname\relax
+ \expandafter\expandafter\expandafter\@secondoftwo
+ \else
+ \expandafter\expandafter\expandafter\@firstoftwo
+ \fi
+ \else
+ \expandafter\@secondoftwo
+ \fi
+}
+\skvnewdef*\skvifnamedefFT#1{\skvifnamedefTF{#1}\@secondoftwo\@firstoftwo}
+\skvnewdef*\skv@ifx@#1#2\skv@ifx@nil{\expandafter#1}
+\skvnewdef*\skv@ifx@@#1#2\skv@ifx@nil{#1}
\skvnewdef*\skvifxTF#1#2{%
\csname @\expandafter\expandafter\expandafter
\ifx\skv@ifx@#1\batchmode\skv@ifx@nil\skv@ifx@@#2\noboundary\skv@ifx@nil
@@ -484,8 +592,6 @@
}%
}%
}
-
-\let\then\iffalse
\begingroup
% Keep lccode, in case the test occurs in a table:
\lccode`\&=0 \catcode`\&=8
@@ -508,7 +614,7 @@
\csname @\csname if#1\endcsname
first\else second\fi oftwo\endcsname
}{%
- \skv@err{Undefined boolean '#1'}\@ehd
+ \skv@err{Undefined boolean '#1'}\skv@ehd
}%
}%
}
@@ -519,6 +625,12 @@
\csname @\csname if#1\endcsname first\else second\fi oftwo\endcsname
}
\skvnewdef*\skvifdefboolFT#1{\skvifdefboolTF{#1}\@secondoftwo\@firstoftwo}
+\skvrobustdef*\skvaftergroupifboolTF#1\endgroup{%
+ \skvifboolTF{#1}{\endgroup\@firstoftwo}{\endgroup\@secondoftwo}%
+}
+\skvrobustdef*\skvaftergroupifboolFT#1\endgroup{%
+ \skvifboolTF{#1}{\endgroup\@secondoftwo}{\endgroup\@firstoftwo}%
+}
% \skvifboolvalTF{<toks>}{<true>}{<false>}
\skvrobustdef*\skvifboolvalTF#1{%
\skvxifinTF{,\expandafter\skvtrimspace\expandafter
@@ -553,13 +665,13 @@
\skvaftergroupdef#2\endgroup
}
\skvrobustdef*\skv@badboolerr#1{%
- \skv@err{Invalid boolean value '#1'; expected 'true' or 'false'}\@ehd
+ \skv@err{Invalid boolean value '#1'; expected 'true' or 'false'}\skv@ehd
}
% Switches and toggles have separate namespaces.
\skvrobustdef*\skvnewswitch#1{%
\skvifcsdefTF{skv@switch@#1}{%
- \skv@err{Switch '\detokenize{#1}' already exists}\@ehd
+ \skv@err{Switch '\detokenize{#1}' already exists}\skv@ehd
}{%
\skvcsdef{skv@switch@#1}{01}%
}%
@@ -581,19 +693,19 @@
\skvifcsdefTF{skv@switch@#1}{%
\skvcsdef{skv@switch@#1}{00}%
}{%
- \skv@err{No switch '\detokenize{#1}'}\@ehd
+ \skv@err{No switch '\detokenize{#1}'}\skv@ehd
}%
}
\skvrobustdef*\skvswitchfalse#1{%
\skvifcsdefTF{skv@switch@#1}{%
\skvcsdef{skv@switch@#1}{01}%
}{%
- \skv@err{No switch '\detokenize{#1}'}\@ehd
+ \skv@err{No switch '\detokenize{#1}'}\skv@ehd
}%
}
\skvrobustdef*\skvnewtog#1{%
\skvifcsdefTF{skv@toggle@#1}{%
- \skv@err{Switch '\detokenize{#1}' already exists}\@ehd
+ \skv@err{Switch '\detokenize{#1}' already exists}\skv@ehd
}{%
\skvcslet{skv@toggle@#1}\@secondoftwo
}%
@@ -612,14 +724,14 @@
\skvifcsdefTF{skv@toggle@#1}{%
\skvcslet{skv@toggle@#1}\@firstoftwo
}{%
- \skv@err{No toggle '\detokenize{#1}'}\@ehd
+ \skv@err{No toggle '\detokenize{#1}'}\skv@ehd
}%
}
\skvrobustdef*\skvsettogfalse#1{%
\skvifcsdefTF{skv@toggle@#1}{%
\skvcslet{skv@toggle@#1}\@secondoftwo
}{%
- \skv@err{No toggle '\detokenize{#1}'}\@ehd
+ \skv@err{No toggle '\detokenize{#1}'}\skv@ehd
}%
}
@@ -630,18 +742,6 @@
\skvnewdef*\skvifplaswFT#1{%
\if#1\expandafter\@secondoftwo\else\expandafter\@firstoftwo\fi
}
-% \def\swa{01} \def\swb{01}
-% \if\skvnegateplasw\swa...\else...\fi
-% \if\skvifbothplaswtrue\swa\swb...\else...\fi
-% \if\skvifoneplaswtrue\swa\swb...\else...\fi
-\skvnewdef*\skvnegateplasw#1{0\skvifplaswTF{#1}10}%
-\skvnewdef*\skvifbothplaswtrue#1#2{%
- 0\ifcase#1#2 \expandafter0\else\expandafter1\fi
-}
-\skvnewdef*\skvifoneplaswtrue#1#2{%
- 0\ifnum#1#2<101 \expandafter0\else\expandafter1\fi
-}
-
\skvnewdef\skvifcondTF#1\fi{%
\csname @#1first\else second\fi oftwo\endcsname
}
@@ -670,21 +770,33 @@
\skvrobustdef*\skvgundef#1{\global\let#1\@undefined}
\skvrobustdef*\skvcsundef#1{\skvcslet{#1}\@undefined}
\skvrobustdef*\skvcsgundef#1{\global\skvcslet{#1}\@undefined}
+\skvrobustdef*\skvemptify#1{\skv@commaact{#1}{\def##1{}}}
+\skvrobustdef*\skvinizero#1{\skv@commaact{#1}{\def##1{0}}}
\skvrobustdef*\skvundefcmdlist#1{%
\skvcommaparse{#1}\skv@prova{\expandafter\skvundef\skv@prova}%
}
\skvrobustdef*\skvemptifycmds#1{%
\skvcommaparse{#1}\skv@prova{\expandafter\def\skv@prova{}}%
}
-\skvrobustdef*\skvemptify#1{\def\do##1{\def##1{}}#1}
+% \skv@addtocollection{<toks>}
+%
+% Collect tokens in a group for later exiting the group with them:
+%
+\skvrobustdef*\skv@addtocollection#1{%
+ \edef\skv@collection{%
+ \ifdefined\skv@collection\skvexpandonce\skv@collection\fi
+ \unexpanded{#1}%
+ }%
+}
+% Don't use \do for \dl, in case \do appears as a garbage:
+% \skvgarbageitems{\dl<cmd1>\gdl<cmd2>...}
+\skvrobustdef*\skvgarbageitems{\skvappto\skv@garbagelist}
\skvrobustdef*\skvdumpgarbage{%
- \let\gdl\skvgundef
- \let\dl\skvundef
+ \let\gdl\skvgundef\let\dl\skvundef
\skv@garbagelist
\def\skv@garbagelist{}%
}
-% \skvgarbageitems{\dl<cmd1>\gdl<cmd2>...}
-\skvrobustdef*\skvgarbageitems{\skvappto\skv@garbagelist}
+
\skvifdefTF\pdfstrcmp{%
\let\skv@strcmp\pdfstrcmp
}{%
@@ -692,8 +804,7 @@
\skvifdefTF\pdf@strcmp{%
\let\skv@strcmp\pdf@strcmp
}{%
- \skv@err{Neither '\string\pdfstrcmp' nor
- '\string\pdf@strcmp' exists}\@ehd
+ \skv@err{Neither '\string\pdfstrcmp' nor '\string\pdf@strcmp' exists}\skv@ehd
}%
}
\skvnewdef\skvifstrcmpTF#1#2{%
@@ -715,7 +826,7 @@
\skvrobustdef\skvcslet#1#2{\expandafter\let\csname#1\endcsname#2}
\skvrobustdef\skvnewcslet#1{%
\skvifcsdefTF{#1}{%
- \skv@err{Command '\skvnoexpandcs{#1}' already defined}\@ehd
+ \skv@err{Command '\skvnoexpandcs{#1}' already defined}\skv@ehd
}{%
\skvcslet{#1}%
}%
@@ -726,7 +837,7 @@
}
\skvrobustdef\skvnewletcs#1{%
\skvifdefTF{#1}{%
- \skv@err{Command '\string#1' already defined}\@ehd
+ \skv@err{Command '\string#1' already defined}\skv@ehd
}{%
\skvletcs#1%
}%
@@ -738,7 +849,7 @@
}
\skvrobustdef\skvnewcsletcs#1{%
\skvifcsdefTF{#1}{%
- \skv@err{Command '\skvnoexpandcs{#1}' already defined}\@ehd
+ \skv@err{Command '\skvnoexpandcs{#1}' already defined}\skv@ehd
}{%
\skvcsletcs{#1}%
}%
@@ -755,12 +866,16 @@
\skvexpanded{\endgroup\expandafter\skvcmdexit\csname#1\endcsname}%
}
-% Taking command and booleans out of a local group under \edef:
+% Taking commands and booleans out of a local group under \edef:
\skvnewdef*\skvcmdexit#1{%
- \edef\noexpand#1{\noexpand\unexpanded{\skvexpandonce{#1}}}%
+ \skvifdefTF{#1}{%
+ \edef\noexpand#1{\noexpand\unexpanded{\skvexpandonce{#1}}}%
+ }{}%
}
\skvnewdef*\skvcsexit#1{%
- \skvcsedef{#1}{\noexpand\unexpanded{\skvexpandcsonce{#1}}}%
+ % If #1 is undefined, \skvexpandcsonce will make it relax. The
+ % preliminary test in \skvcmdexit will deal with that situation.
+ \skvaftercs\skvcmdexit{#1}%
}
% \edef\x{\endgroup\skvcmdexitloop{\x\y}}:
\skvnewdef*\skvcmdexitloop#1{\skv@cmdexitloop#1\end}
@@ -776,6 +891,7 @@
\skvnewdef*\skv@boolexitloop#1{%
\ifx\end#1\else\skvboolexit{#1}\expandafter\skv@boolexitloop\fi
}
+
\skvnewdef*\skvprotect#{%
\ifx\protect\@typeset@protect\skv@protect\@firstofone\fi
\ifx\protect\@unexpandable@protect\skv@protect\skvunexpandable\fi
@@ -791,13 +907,14 @@
\expandafter\endgroup\ifx\skv@prova\skv@nnil
\expandafter\@gobble\else\expandafter\@firstofone\fi
}
-
+% \skvadvanceno{<cmd>}{<number>}
\skvrobustdef*\skvsetnumber#1{%
\begingroup
\def\x{\edef\x{\endgroup\def\noexpand#1{\the\count@}}\x}%
\afterassignment\x\count@
}
\skvnewlet\skvsetno\skvsetnumber
+% \skvadvanceno{<cmd>}{<number>}
\skvrobustdef*\skvadvanceno{\skv@advanceno\relax}
\skvrobustdef*\skvgadvanceno{\skv@advanceno\global}
\skvrobustdef*\skv@advanceno#1#2#3{%
@@ -808,7 +925,7 @@
\skvifdefTF#2{%
#1\edef#2{\the\numexpr#2+#3\relax}%
}{%
- \skv@err{Number '\string#2' is not defined}\@ehd
+ \skv@err{Number '\string#2' is not defined}\skv@ehd
}%
}
\skvrobustdef*\skvpushnumber#1{%
@@ -822,20 +939,25 @@
\skvifdefTF#1{%
\edef#1{\the\numexpr#1+1\relax}%
}{%
- \skv@err{Number '\string#1' is not defined}\@ehd
+ \skv@err{Number '\string#1' is not defined}\skv@ehd
}%
}
\skvrobustdef\skv@testst#1{%
\skvifstar{\skv@tempsttrue#1}{\skv@tempstfalse#1}%
}
+% For internal use:
+\skvrobustdef\skv@i@ifstar#1{\@ifnextchar*{\@firstoftwo{#1}}}
+\skvrobustdef\skv@i@testst#1{%
+ \skv@i@ifstar{\skv@tempsttrue#1}{\skv@tempstfalse#1}%
+}
\skvrobustdef\skv@testcl#1{%
\skvifnextchar!{\skv@cltrue#1}{\skv@clfalse#1}%
}
\skvrobustdef\skv@teststopt#1#2{\skv@testst{\skv@testopt{#1}{#2}}}
-
-% Removing spurious spaces before checking for brace.
+% Remove spurious leading and trailing spaces before checking for outer brace.
+% Such spaces do hide the outer brace.
% If we were to use \skvtrimspace for \skvifbracedTF, then the need
% for double \romannumeral will cause problems of premature expansion.
\begingroup
@@ -859,28 +981,38 @@
\skvnewdef\skvifbracedFT#1{\skvifbracedTF{#1}\@secondoftwo\@firstoftwo}
% \skvstripouterbraces{<nr>}<cmd>
+% Example:
+% \def\x{{{{X}}}}
+% \skvstripouterbraces{2}\x
\skvrobustdef*\skvstripouterbraces#1#2{%
- \begingroup
- \@tempcnta\skvz@
- \expandafter\skv@stripouterbraces#2\strip@nil{#2}{#1}%
+ \skvifemptyTF#2{}{%
+ \begingroup
+ \@tempcnta\skvz@
+ \expandafter\skv@stripouterbraces#2\strip@nil{#2}{#1}%
+ }%
}
\skvrobustdef*\skv@stripouterbraces#1\strip@nil#2#3{%
- \advance\@tempcnta\@ne
- \skvifnumTF\@tempcnta=#3{%
- \edef#2{\unexpanded{#1}}%
+ \edef\skv@prova{\unexpanded{#1}}%
+ \skvifxTF#2\skv@prova{%
\skvaftergroupdef#2\endgroup
}{%
- \skv@stripouterbraces#1\strip@nil{#2}{#3}%
+ \advance\@tempcnta\@ne
+ \skvifnumTF\@tempcnta=#3{%
+ \let#2\skv@prova
+ \skvaftergroupdef#2\endgroup
+ }{%
+ \let#2\skv@prova
+ \expandafter\skv@stripouterbraces#2\strip@nil{#2}{#3}%
+ }%
}%
}
-
\skvrobustdef*\skvifescapedTF#1{%
\begingroup\escapechar92\relax
\edef\x{\expandafter\skv@car\string#1x\car@nil}%
\expandafter\endgroup
\csname @\ifx\x\@backslashchar first\else second\fi oftwo\endcsname
}
-\skvnewdef\skvifnotescaped#1{\skvifescapedTF{#1}\@secondoftwo\@firstoftwo}
+\skvnewdef\skvifescapedFT#1{\skvifescapedTF{#1}\@secondoftwo\@firstoftwo}
\skvnewdef*\skvremovescape#1{\expandafter\@gobble\string#1}
\skvnewdef*\skvgobblescape#1{%
\skvifblankTF{#1}{}{%
@@ -908,7 +1040,13 @@
}
\skvnewdef*\skvnoexpandcs#1{\skvexpandonce{\csname#1\endcsname}}
\skvnewdef*\skvexpandcsonce#1{%
- \unexpanded\expandafter\expandafter\expandafter{\csname#1\endcsname}%
+ \expandafter\skvexpandonce\expandafter{\csname#1\endcsname}%
+}
+\skvnewdef*\skvexpandcstwice#1{%
+ \expandafter\skvexpandtwice\expandafter{\csname#1\endcsname}%
+}
+\skvnewdef*\skvexpandcsthrice#1{%
+ \expandafter\skvexpandthrice\expandafter{\csname#1\endcsname}%
}
\skvrobustdef\skvexpanded#1{\begingroup\edef\x{\endgroup#1}\x}
\skvrobustdef\skvexpandarg#1#2{\skvexpanded{\unexpanded{#1}{#2}}}
@@ -928,8 +1066,15 @@
\expandafter\skvswap\expandafter{\expandafter{#2}}{#1}%
}
\skvnewlet\skvexpbracenext\skvexpandbracenext
+% Eg, \skvexpandintonext\x[\y], \skvexpandintonext\x{\y}.
+% This isn't expandable, because #1 may not be just one token.
+\skvnewdef\skvexpandintonext#1{%
+ \begingroup
+ \edef\reserved@a{\endgroup\unexpanded{#1}}%
+ \expandafter\reserved@a\expandafter
+}
\skvrobustdef*\skvifinTF#1#2{%
- \skv@in@{#1}{#2}%
+ \skvtestifin{#1}{#2}%
\csname @\ifin@ first\else second\fi oftwo\endcsname
}
\skvrobustdef*\skvifinFT#1#2{\skvifinTF{#1}{#2}\@secondoftwo\@firstoftwo}
@@ -938,40 +1083,164 @@
\skvrobustdef*\skvifindetokTF#1#2#3{%
\skvexpandtwoargs\skvifinTF{#1\skvoxdetok{#2}#1}{#1\skvoxdetok{#3}#1}%
}
-\skvnewdef\skviffound#1\in#2\then{\skv@in@{#1}{#2}\ifin@}
-\skvnewdef\skvxiffound#1\in#2\then{\skvexpandtwoargs\skv@in@{#1}{#2}\ifin@}
+\skvnewdef\skviffound#1\in#2\then{\skvtestifin{#1}{#2}\ifin@}
+\skvnewdef\skvxiffound#1\in#2\then{\skvexpandtwoargs\skvtestifin{#1}{#2}\ifin@}
% \skv@kvsplit{<kvpair>}{<parametered.callback>}
\skvrobustdef*\skv@kvsplit#1#2{%
\begingroup
- \def\skv@tempa##1=##2=##3\skv@kvsplit{%
- \endgroup#2%
- }%
+ \def\skv@tempa##1=##2=##3\skv@kvsplit{\endgroup#2}%
\skv@tempa#1==\skv@kvsplit
}
-\skvrobustdef*\skv@kvosplit#1{\skvexpbracenext\skv@kvsplit{#1}}
-% \skv@slsplit{<slashlist>}{<parametered.callback>}
-\skvrobustdef*\skv@slsplit#1#2{%
+\skvrobustdef*\skv@okvsplit#1{\skvexpbracenext\skv@kvsplit{#1}}
+% \skv@slashsplit{<slashlist>}{<parametered.callback>}
+% Patrons calling \skv@slashsplit should note that it may return
+% ^skv^ for any missing components:
+\skvrobustdef*\skv@slashsplit#1#2{%
\begingroup
- \def\skv@tempa##1/##2/##3/##4/##5/##6/##7/##8/##9\skv@slsplit{%
+ \def\skv@tempa##1/##2/##3/##4/##5/##6/##7/##8/##9\skv@slashsplit{%
\endgroup#2%
}%
- \skv@tempa#1/^skv^/^skv^/^skv^/^skv^/^skv^/^skv^/^skv^/\skv@slsplit
+ \skv@tempa#1/^skv^/^skv^/^skv^/^skv^/^skv^/^skv^/^skv^/^skv^\skv@slashsplit
}
-\skvnewlet\skv@slashsplit\skv@slsplit
-\skvrobustdef*\skv@slosplit#1{\skvexpbracenext\skv@slsplit{#1}}
+\skvrobustdef*\skv@oslashsplit#1{\skvexpbracenext\skv@slashsplit{#1}}
-\skvrobustdef*\skv@rescan#1{%
+% \skv@splitpath@a{<path.macro>}{<pref.macro>}{<fam.macro>}
+% Here, <path.macro> has the form {<pref>/<fam>}.
+\skvrobustdef*\skv@splitpath@a#1#2#3{%
\begingroup
- \endlinechar\m@ne\newlinechar\m@ne
- \catcode`\@=11
- \everyeof{\skv@rescan@}%
- \def\reserved@a##1\skv@rescan@{%
- \endgroup\edef#1{\unexpanded{##1}}%
+ \ifx#1\@empty
+ \skv@err{No key can have empty path}\skv@ehd
+ \else
+ \skv@oslashsplit{#1}{%
+ \edef#2{\skvtrimspace{##1}}%
+ \edef#3{\skvtrimspace{##2}}%
+ \skvstripouterbraces{2}#2%
+ \skvstripouterbraces{2}#3%
+ \ifx#3\skv@rej
+ \let#3#2%
+ \let#2\skvdefaultprefix
+ \fi
+ }%
+ \fi
+ \skvexpanded{\endgroup\skvcmdexit#2\skvcmdexit#3}%
+}
+% \skv@splitpath@b{<path.macro>}{<pref.macro>}{<fam.macro>}
+% Here, <path.macro> has the form {<pref>}{<fam>}.
+% Here, we don't expect to find empty entries in #1, since
+% \skv@splitpath@a wouldn't have made such an entry in #1. But don't
+% mind, let us still test for empty.
+\skvrobustdef*\skv@splitpath@b#1#2#3{%
+ \begingroup
+ \def\skv@prova##1##2\@nil{%
+ \edef#2{\skvtrimspace{##1}}%
+ \edef#3{\skvtrimspace{##2}}%
+ \ifx#3\@empty
+ \let#3#2%
+ \let#2\skvdefaultprefix
+ \fi
+ }%
+ \expandafter\skv@prova#1\@nil
+ \skvexpanded{\endgroup\skvcmdexit#2\skvcmdexit#3}%
+}
+% \skv@formatpaths{<paths>}{<macro.to.reveive.formated.paths>}
+%
+% Format <paths> given in the form
+%
+% {<pref1>/<fam1>},...,{<pref-n>/<fam-n>}
+%
+% into
+%
+% \skv@pathdo{<pref1>}{<fam1>}...\skv@pathdo{<pref-n>}{<fam-n>}
+%
+\skvrobustdef*\skv@formatpaths#1#2{%
+ \begingroup
+ \skvifdefTF#2{}{\def#2{}}%
+ \edef\skv@prova{#1}%
+ \skvcsvnormalize[/]\skv@prova
+ \skvcommaparse*\skv@prova\skv@prova{%
+ \skv@splitpath@a\skv@prova\skv@tempa\skv@tempb
+ \edef\skv@prova{{\skv@tempa}{\skv@tempb}}%
+ \skvxifinTF{\skvoxdetok\skv@prova}{\skvoxdetok{#2}}{}{%
+ \edef#2{\skvexpandonce#2\noexpand\skv@pathdo\skv@prova}%
+ }%
+ }%
+ \skvaftergroupdef#2\endgroup
+}
+% \skv@makepaths{<prefix.macro>}{<families.macro>}{<pathlist.macro>}
+% {<wrapper.macro>}
+%
+% Attach prefix to families, to make pathlist. <prefix> must contain
+% only one element.
+%
+\skvrobustdef*\skv@makepaths#1#2#3#4{%
+ \begingroup
+ \skv@ifnoprefix#1{\let#1\skvdefaultprefix}{}%
+ \edef\skv@pref{#1}%
+ \skvdespacecontent\skv@pref
+ \skvstripouterbraces{2}\skv@pref
+ \skv@ifoneprefix\skv@pref{%
+ \skvifdefTF#3{}{\def#3{}}%
+ \skvcommaparse*#2\skv@prova{%
+ \skvstripouterbraces{2}\skv@prova
+ \edef\skv@prova{{\skv@pref}{\skv@prova}}%
+ \skvxifinTF{\skvoxdetok\skv@prova}{\skvoxdetok{#3}}{}{%
+ \edef#3{\skvexpandonce{#3}\noexpand#4\skv@prova}%
+ }%
+ }%
+ }{%
+ \skv@err{Only one prefix allowed here}
+ {The service you've called takes only one key prefix}%
+ }%
+ \skvaftergroupdef#3\endgroup
+}
+% \skv@ifoneprefix{<prefix>}
+\skvrobustdef*\skv@ifoneprefix#1{%
+ \skvxifinTF{,}{\skvoxdetok{#1}}{%
+ \begingroup
+ \def\skv@prova##1,##2\skv@nil{%
+ \endgroup
+ \skvifblankTF{##2}{%
+ \def#1{##1}%
+ }{%
+ \@secondoftwo
+ }%
+ }%
+ \expandafter\skv@prova#1\skv@nil
+ }{%
+ \@firstoftwo
+ }%
+}
+% \skv@ifnoprefix{<prefix.macro>}
+\skvrobustdef*\skv@ifnoprefix#1{%
+ % Think twice before changing this conditional!
+ \ifcase0%
+ \ifx#1\skv@undefined\else\ifx#1\@empty\else 1\fi\fi\relax
+ \expandafter\@firstoftwo
+ \else
+ \expandafter\@secondoftwo
+ \fi
+}
+\skvrobustdef*\skvifmacroTF#1{%
+ \skvifntypeTF{#1}{%
+ \begingroup
+ \edef\skv@tempa##1{\def##1####1\detokenize{macro}:####2\skvrelax}%
+ \skv@tempa\skv@tempa{%
+ \expandafter\endgroup\ifx\@nnil##2\@nnil
+ \expandafter\@secondoftwo
+ \else
+ \expandafter\@firstoftwo
+ \fi
+ }%
+ \edef\skv@tempb##1{##1\detokenize{macro}:\skvrelax}%
+ \skv@tempb{\expandafter\skv@tempa\meaning#1}%
+ }{%
+ \@secondoftwo
}%
- \expandafter\reserved@a\scantokens\expandafter{#1}%
}
+\skvrobustdef*\skvifmacroFT#1{\skvifmacroTF{#1}\@secondoftwo\@firstoftwo}
+% If there is a digit present in #1:
\skvnewdef*\skvifdigitpresentTF#1{%
\skvifcondTF\if0\skvifblankTF{#1}{1}{\skv@ifdigitpresent#1\skv@nnil}\fi
}
@@ -1072,10 +1341,10 @@
}\x
}
\endgroup
-\skvdefregistertester\skip\skvifskip
-\skvdefregistertester\count\skvifcount
-\skvdefregistertester\dimen\skvifdimen
-\skvdefregistertester\toks\skviftoks
+\skvdefregistertester\skip\skvifskipTF
+\skvdefregistertester\count\skvifcountTF
+\skvdefregistertester\dimen\skvifdimenTF
+\skvdefregistertester\toks\skviftoksTF
% Converting units.
% Examples:
@@ -1134,17 +1403,17 @@
% \skvifdimensionable{1pt\relax\skvrelax}{\def\x{T}}{\def\x{F}}
%
-\skvnewregister\bool\ifskv@isinteger
+\skvnewregister\bool{\ifskv@isinteger}
% In case the argument of \skvifintegerTF containes \numexpr:
\skvnewlet\skv@catch@nil\relax
-% #1: Essence, #2: Test token
+% \skvensureinteger{<essence>}{<test token>}
\skvrobustdef*\skvensureinteger#1#2{%
\begingroup
\def\skv@prova##1\skv@catch@nil{%
% If ##1 is empty or contains nothing before a \relax, it's fine:
\ifx\relax##1\relax\else
- \skv@err{Token '#2' for '#1' isn't an integer}\@ehd
+ \skv@err{Token '#2' for '#1' isn't an integer}\skv@ehd
\fi
}%
\afterassignment\skv@prova\skv@cnta#2\relax\skv@catch@nil
@@ -1170,7 +1439,7 @@
\def\skv@dimunit{}%
% Does 'pt' mean 0pt or 1pt? Make it an invalid input:
\lowercase{\skvifindetokTF{,}{#1}}\skv@validunit{%
- \@latexerr{Illegal step '#1': no number found with it}\@ehd
+ \skv@err{Illegal step '#1': no number found with it}\skv@ehd
}{}%
\skv@isintegerfalse
\skvifintegerTF{#1}{%
@@ -1214,7 +1483,7 @@
\skvifinTF{,#1,}{,\hsize,\vsize,}{%
\skv@provb
}{%
- \skvifdimen{#1}{%
+ \skvifdimenTF{#1}{%
\skv@provb
}{%
\lowercase{\skvifindetokTF{,}{#1#2}}\skv@validunit{%
@@ -1299,7 +1568,7 @@
\skvifinTF{*}{#1}{%
\skvifinTF{/}{#1}{%
\skv@err{I can't parse this: both star (*) and slash
- \MessageBreak (/) are in '#1'}\@ehd
+ \MessageBreak (/) are in '#1'}\skv@ehd
}{%
\skvifblankTF{#1}{}{\skv@dimexpr@times#1*\skv@catch@nil}%
}%
@@ -1378,7 +1647,7 @@
\skvrobustdef*\skvnormalize#1#2#3#4{%
\def\skv@prova##1#1##2##3\skv@nil{%
\ifx\skv@nnil##2%
- \skv@err{Invalid list type '#1' for command \string\skvnormalize}\@ehd
+ \skv@err{Invalid list type '#1' for command \string\skvnormalize}\skv@ehd
\fi
\edef#4{\unexpanded{#3}}%
##2[#2]#4%
@@ -1412,6 +1681,7 @@
\do#2,\skv@nil,%
\expandafter\endgroup\the\toks@
}
+% \skvkvnormalize{<kvlistcmd>}
\skvrobustdef*\skvkvnormalize#1{%
\begingroup
\skv@setupnormalizer{,}%
@@ -1518,7 +1788,7 @@
}%
\def\skv@parserequalerr##1#1=##2\normal@nil{%
\skvifblankTF{##2}{}{%
- \skv@err{There is '#1=' in your key-value list}\@ehd
+ \skv@err{There is '#1=' in your key-value list}\skv@ehd
}%
}%
}
@@ -1586,7 +1856,60 @@
{\skv@mac@doubleparser##1#1##2\normal@nil}%
}%
}
-% \skvpushfunctions<base-fn>{<fn-list>}<cnt>
+% \skvletmanytocmd{<cmd list>}{<cmd>}
+\skvrobustdef*\skvletmanytocmd#1#2{%
+ \skvcommaparse{#1}\skv@prova{%
+ \expandafter\let\skv@prova= #2%
+ }%
+}
+% \skvnewletmanytocmd{<cmd list>}{<cmd>}
+\skvrobustdef*\skvnewletmanytocmd#1#2{%
+ \skvcommaparse{#1}\skv@prova{%
+ \expandafter\skv@newcastcommand\skv@prova=#2=\cast@nil
+ }%
+}
+% \skvcastcommands{<cmd list>}
+%
+% <cmd list> -> {<cmd-a1>=<cmd-a2>,...,<cmd-b1>=<cmd-b2>}
+%
+% In <cmd list>, cast left-hand command to the right-hand command.
+% Raise error if left-hand command already exists and isn't equal to
+% the right-hand command.
+%
+% Example:
+%
+% \skvcastcommands{\ifxx=\ifx,\fii=\fi}
+%
+\skvrobustdef*\skvcastcommands#1{%
+ \def\skv@provb##1=##2=##3\cast@nil{\let##1= ##2}%
+ \skvkvparse{#1}\skv@prova{%
+ \expandafter\skv@provb\skv@prova==\cast@nil
+ }%
+}
+% \skvnewcastcommands{<cmd list>}
+%
+% <cmd list> -> {<cmd-a1>=<cmd-a2>,...,<cmd-b1>=<cmd-b2>}
+%
+\skvrobustdef*\skvnewcastcommands#1{%
+ \skvkvparse{#1}\skv@prova{%
+ \expandafter\skv@newcastcommand\skv@prova==\cast@nil
+ }%
+}
+\skvrobustdef*\skv@newcastcommand#1=#2=#3\cast@nil{%
+ \skvifdefTF{#1}{%
+ \ifx#1#2\else
+ \skv@err{Command \noexpand#1 already exists:
+ \MessageBreak it can't be cast to \string#2}\skv@ehd
+ \fi
+ }{%
+ \let#1= #2%
+ }%
+}
+% \skvpushfunctions<base-fn>{<fn-list>}<counter-number>
+%
+% 1. <counter-number> is a number, not a counter.
+% 2. See file skeyval-for.tex for \skvsavestate and \skvrestorestate.
+%
\skvrobustdef*\skvpushfunctions#1#2#3{%
\skvgadvanceno#3\@ne
\begingroup
@@ -1601,16 +1924,16 @@
\def\do##1{\let\skvnoexpandcs{\skv@prova{##1}}\noexpand##1}%
\skvexpanded{\endgroup#2}%
}
-% \skvpopfunctions<base-fn><counter>
+% \skvpopfunctions<base-fn><counter-number>
\skvrobustdef*\skvpopfunctions#1#2{%
\begingroup
\edef\skv@elt{\skvnoexpandcs{\skvremovescape{#1}@skv@stack}}%
\expandafter\skvifdefTF\skv@elt{%
\expandafter\ifx\skv@elt\@empty
- \skv@err{Stack of '\noexpand#1' is empty}\@ehd
+ \skv@err{Stack of '\noexpand#1' is empty}\skv@ehd
\fi
}{%
- \skv@err{Stack of '\noexpand#1' is undefined}\@ehd
+ \skv@err{Stack of '\noexpand#1' is undefined}\skv@ehd
}%
\edef\skv@prova{\skvexpandtwice\skv@elt}%
\edef\skv@provb##1##{\endgroup##1\gdef\skvexpandonce\skv@elt}%
@@ -1619,11 +1942,15 @@
}
\chardef\skv@stackdepthlimit=6\relax
-% #1=stack (macro), #2=list, #3=max depth
+% #1=stack (a macro), #2=list, #3=max depth
\skvrobustdef*\skvbuildmacrostack#1#2#3{%
\begingroup
\escapechar92\relax
- \@ifdefinable#1{\def#1{}}%
+ \ifdefined#1%
+ \skv@err{Stack \noexpand#1 already exists}\skv@ehd
+ \else
+ \def#1{}%
+ \fi
\@tempcnta\skvz@
\def\do##1{%
\noexpand\skv@elt\noexpand##1%
@@ -1651,13 +1978,13 @@
\def\skv@elt##1##2{\let##2=##1}%
\else
\ifnum#2<\@ne
- \skv@err{Can't pop stack: depth currently less than 1}\@ehd
+ \skv@err{Can't pop stack: depth currently less than 1}\skv@ehd
\else
\def\skv@elt##1##2{\let##1=##2}%
\fi
\fi
\ifnum#2>\skv@stackdepthlimit
- \skv@err{Stack depth limit '\number\skv@stackdepthlimit' exceeded}\@ehd
+ \skv@err{Stack depth limit '\number\skv@stackdepthlimit' exceeded}\skv@ehd
\fi
\def\skv@prova##1{%
\def\skv@prova####1.##1.####2####3\skv@nil{####2}%
@@ -1677,7 +2004,7 @@
\def\do##1,{%
\ifx\do##1\else
\skvifcsdefTF{if#1##1}{%
- \skv@err{Boolean '\skvnoexpandcs{if#1##1}' already exists}\@ehd
+ \skv@err{Boolean '\skvnoexpandcs{if#1##1}' already exists}\skv@ehd
}{%
\toks@\expandafter{\the\expandafter\toks@
\csname newif\expandafter\endcsname\csname if#1##1\endcsname}%
@@ -1688,18 +2015,35 @@
\expandafter\do\skv@prova,\do,%
\expandafter\endgroup\the\toks@
}
-% \ifskv@inoptionsec determines if we're in skeyval options section or not.
-% Some checks are done in that section.
+% Some booleans:
+%
+% inset = in \skvsetkeys
+% viarootofsetkeys = a key is being set via the root of the command
+% \skvsetkeys. This is needed because sometimes we
+% bypass the root of \skvsetkeys, eg, by calling
+% \skv@setkeys@a.
+% inclass = in class file.
+% kf = key has been found while in \skvsetkeys.
+% intry = in 'try set keys'.
+% insa = in 'search also set keys'.
+% success = key has been found while in 'try set keys'.
+% inopt = in process/execute options.
+% inpox = in process options.
+% inprepo = presetting or post-setting keys.
+% inoptionsec = in skeyval package's options processing section.
+% Some checks are done in that section.
+%
\skvnewbools[skv@]{%
- inset,st,cl,pl,kf,inpox,prepo,tracingkeys,swa,swb,verbose,%
- intry,insa,success,inoptionsec,inopt,handlerswa,handlerswb%
+ inclass,inset,viarootofsetkeys,processvalueaslist,st,cl,pl,kf,inpox,inopt,%
+ inprepo,tracingkeys,swa,swb,verbose,intry,insa,success,inoptionsec,%
+ inreservedhandler,ignorepointers%
}
-%\skvnewbools{indirkeys}
-\skvnewbools[skv]{indef,indirkeys,novalue,valuebraced}
+\skvnewbools{indirectkeys}
+\skvnewbools[skv]{indef,novalue,valuebraced}
\skvnewbools[dirkeys@]{saveunknownkeys}
-
+% \skvnewcounts[<optional prefix>]{<name list>}
\skvrobustdef*\skvnewcounts{\skv@testopt\skv@newcounts{}}
\skvrobustdef*\skv@newcounts[#1]#2{%
\begingroup
@@ -1709,7 +2053,7 @@
\def\do##1,{%
\ifx\do##1\else
\skvifcsdefTF{#1##1}{%
- \skv@err{Counter '\skvnoexpandcs{#1##1}' already exists}\@ehd
+ \skv@err{Counter '\skvnoexpandcs{#1##1}' already exists}\skv@ehd
}{%
\toks@\expandafter{\the\expandafter\toks@
\csname newcount\expandafter\endcsname\csname#1##1\endcsname}%
@@ -1720,8 +2064,8 @@
\expandafter\do\skv@prova,\do,%
\expandafter\endgroup\the\toks@
}
-\skvnewcounts[skv@]{cnta,cntb}
-
+\skvnewcounts[skv@]{tempcnt,cnta}
+% \skvnewnumbers[<optional prefix>]{<name list>}
\skvrobustdef*\skvnewnumbers{\skv@testopt\skv@newnumbers{}}
\skvrobustdef*\skv@newnumbers[#1]#2{%
\begingroup
@@ -1731,7 +2075,7 @@
\def\do##1,{%
\ifx\do##1\else
\skvifcsdefTF{#1##1}{%
- \skv@err{Number '\skvnoexpandcs{#1##1}' already exists}\@ehd
+ \skv@err{Number '\skvnoexpandcs{#1##1}' already exists}\skv@ehd
}{%
\toks@\expandafter{\the\expandafter\toks@
\expandafter\def\csname#1##1\endcsname{0}}%
@@ -1742,9 +2086,9 @@
\expandafter\do\skv@prova,\do,%
\expandafter\endgroup\the\toks@
}
-
-\skvnewnumbers[skv@]{keydepth,setkeysdepth,makekeysdepth,
- usekeysdepth,trysetkeysdepth,trysetkeysdepth@b,gendepth}
+\skvnewlet\skvnewnumber\skvnewnumbers
+\skvnewnumbers[skv@]{keydepth,setkeysdepth,preposetdepth,makekeysdepth,
+ usekeysdepth,trysetkeysdepth,trysetkeysidepth,gendepth}
\skvnewnumbers{dirkeys@depth}
\skvnewlet\skv@novalue\relax
\skvnewdef*\skv@novaluetoks{\skv@novalue}
@@ -1754,8 +2098,9 @@
% \quickkeys.define{<family>}[<hp>]{<list>}
% \quickkeys.set{<family>}[<na>]{<kvlist>}
%
-% 1. Quickly defines and set command/store keys.
-% 2. Pointers aren't used here, to speed up parsing.
+% 1. Quickly define and set command/store keys.
+% 2. Pointers aren't used here, to speed up parsing. Use other key
+% machineries instead.
% 3. Package and class options can't be passed via quick keys.
% 4. When defining keys, the syntax of <list> is:
%
@@ -1768,7 +2113,9 @@
%
% 5. The special keys '.exec' and '.exec code' will simply execute the
% code <default>, without defining anything.
-% 6. Use .na to indicate a missing item that isn't blank or empty.
+% 6. Use the token '.na' to indicate a missing item that isn't blank or empty.
+% 7. The parser for defining the keys can be specified via \setquickkeysparser.
+% The default parser is semicolon (;).
%
% Example:
% \quickkeys.define{fam}[mp@]{%
@@ -1781,22 +2128,14 @@
\skvifstrcmpTF{#1}{^skv^}{%
\@firstoftwo
}{%
- \skvifblankTF{#1}{%
- \@firstoftwo
- }{%
- \@secondoftwo
- }%
+ \skvifblankTF{#1}%
}%
}
\skvnewdef*\skv@ifstrrejordotna#1{%
\skvifstrcmpTF{#1}{^skv^}{%
\@firstoftwo
}{%
- \skvifstrcmpTF{#1}{.na}{%
- \@firstoftwo
- }{%
- \@secondoftwo
- }%
+ \skvifstrcmpTF{#1}{.na}%
}%
}
\skvnewdef*\skv@ifstrnut#1{%
@@ -1806,11 +2145,7 @@
\skvifstrcmpTF{#1}{.na}{%
\@firstoftwo
}{%
- \skvifblankTF{#1}{%
- \@firstoftwo
- }{%
- \@secondoftwo
- }%
+ \skvifblankTF{#1}%
}%
}%
}
@@ -1818,22 +2153,14 @@
\skvifxTF#1\skv@rej{%
\@firstoftwo
}{%
- \skvifemptyTF#1{%
- \@firstoftwo
- }{%
- \@secondoftwo
- }%
+ \skvifemptyTF#1%
}%
}
\skvnewdef*\skv@ifcmdrejordotna#1{%
\skvifxTF#1\skv@rej{%
\@firstoftwo
}{%
- \skvifxTF#1\skv@dotna{%
- \@firstoftwo
- }{%
- \@secondoftwo
- }%
+ \skvifxTF#1\skv@dotna
}%
}
\skvnewdef*\skv@ifcmdnut#1{%
@@ -1843,15 +2170,24 @@
\skvifxTF#1\skv@dotna{%
\@firstoftwo
}{%
- \skvifemptyTF#1{%
- \@firstoftwo
- }{%
- \@secondoftwo
- }%
+ \skvifemptyTF#1%
}%
}%
}
-
+% \skv@qkeysgetkeynames{<kvlist.cmd>}{<return.cmd>}
+\skvrobustdef*\skv@qkeysgetkeynames#1#2{%
+ \begingroup
+ \let#2\@empty
+ \skvkvparse*#1\skv@prova{%
+ \def\do##1=##2=##3\skv@nil{%
+ \edef#2{\skvaddlist,#2##1}%
+ }%
+ \expandafter\do\skv@prova==\skv@nil
+ }%
+ \skvaftergroupdef#2\endgroup
+}
+\skvrobustdef*\skvsetquickkeysparser{\def\skv@qkeysparser}
+\skvsetquickkeysparser{;}
\skvrobustdef*\quickkeys#1#{%
\edef\skv@tempa{\skvtrimspace{#1}}%
\skvxifstrcmpTF{\skvexpandonce\skv@tempa}{.define}{%
@@ -1861,44 +2197,54 @@
\skvxifstrcmpTF{\skvexpandonce\skv@tempa}{.set}{%
\skv@setquickkeys
}{%
- \skv@err{Unknown task for \string\quickkeys}\@ehd
+ \skvxifstrcmpTF{\skvexpandonce\skv@tempa}{.preset}{%
+ \skv@presetquickkeys
+ }{%
+ \skv@err{Unknown task for \string\quickkeys}\skv@ehd
+ }%
}%
}%
}
\skvrobustdef*\skv@defquickkeys#1{\skv@testopt{\skv@defquickkeys@a{#1}}{}}
\skvrobustdef*\skv@defquickkeys@a#1[#2]#3{%
\endgroup
+ \edef\skv@qkeysfam{\skvtrimspace{#1}}%
\edef\skv@tempa{\skvkeepdoubleslashnormalize{#3}}%
- \def\skv@defquickkeys@b##1/##2/##3/##4/##5/##6/##7/##8/##9\skv@nil{%
- \skvifinTF{,##1,}{,.exec,.exec code,}{%
- ##2\relax
- }{%
- % Loop over key list, if there are more than one key:
- \skvparselist{,}{##1}\skv@tempa{%
- % If ##2 is empty, the default will be empty:
- \skv@ifstrrejordotna{##2}{}{%
- \skvcsedef{#1/\skv@tempa/qkeys.def}{\unexpanded{##2}}%
- }%
- \skvcsedef{#1/\skv@tempa/qkeys.cbk}{%
- % ##3 may be empty:
- \skv@ifstrrejordotna{##3}{}{\unexpanded{##3}}%
- }%
- \skv@ifstrnut{##4}{}{%
- \skvcsedef{#1/\skv@tempa/qkeys.chc}{\unexpanded{##4}}%
- }%
- \skv@ifstrnut{##5}{}{%
- \skvcsedef{#1/\skv@tempa/qkeys.arg}{\unexpanded{##5}}%
- }%
- \skvifblankTF{#2}{}{%
- \skvcsedef{#1/\skv@tempa/qkeys.hp}{\unexpanded{#2}}%
+ \skvexpanded{\skvparselist*{\skv@qkeysparser}}\skv@tempa\skv@tempa{%
+ \skv@oslashsplit\skv@tempa{%
+ \skvifinTF{,##1,}{,.exec,.exec code,}{%
+ ##2\relax
+ }{%
+ % Loop over key list, in case there are more than one key:
+ \skvparselist{,}{##1}\skv@tempa{%
+ % If ##2 is empty, the default will be empty:
+ \skv@ifstrrejordotna{##2}{}{%
+ \skvcsedef{\skv@qkeysfam/\skv@tempa/qkeys.def}{\unexpanded{##2}}%
+ }%
+ \skvcsedef{\skv@qkeysfam/\skv@tempa/qkeys.cbk}{%
+ \skvifblankTF{#2}{}{%
+ \skvcsletcs{#2\skv@tempa}{\skv@qkeysfam/\skv@tempa/qkeys.val}%
+ }%
+ \skv@ifstrrejordotna{##3}{}{\unexpanded{##3}}%
+ }%
+ \skv@ifstrnut{##4}{}{%
+ \skvcsedef{\skv@qkeysfam/\skv@tempa/qkeys.chc}{\unexpanded{##4}}%
+ }%
+ \skv@ifstrnut{##5}{}{%
+ \skvcsedef{\skv@qkeysfam/\skv@tempa/qkeys.arg}{\unexpanded{##5}}%
+ }%
}%
}%
}%
}%
- \skvparselist*{;}\skv@tempa\skv@tempa{%
- \expandafter\skv@defquickkeys@b\skv@tempa
- /^skv^/^skv^/^skv^/^skv^/^skv^/^skv^/^skv^/^skv^\skv@nil
- }%
+}
+
+% \quickkeys.preset{<family>}{<kvlist>}
+%
+\skvrobustdef*\skv@presetquickkeys#1#2{%
+ \edef\skv@prova{\unexpanded{#2}}%
+ \skvkvnormalize\skv@prova
+ \skvcslet{\skvtrimspace{#1}/qkeys.preset}\skv@prova
}
\skvnewnumbers[skv@]{setqkeysdepth}
@@ -1907,60 +2253,80 @@
\skvrobustdef*\skv@setquickkeys#1{\skv@testopt{\skv@setquickkeys@a{#1}}{}}
\skvrobustdef*\skv@setquickkeys@a#1[#2]#3{%
- \skvsavestate\skv@setquickkeys{\do\skv@qkeysna}\skv@setqkeysdepth
+ \skvsavestate\skv@setquickkeys{%
+ \do\skv@qkeysfam\do\skv@qkeysna\do\skv@qkeyskvlist
+ \do\skv@qkeyscurrnames
+ }\skv@setqkeysdepth
\edef\skv@qkeysna{\unexpanded{#2}}%
\skvcsvnormalize\skv@qkeysna
- \edef\skv@tempa{\unexpanded{#3}}%
- \skvkvnormalize\skv@tempa
- \def\skv@setqkeys##1##2{%
- \skvifcsdefTF{#1/##1/qkeys.cbk}{}{%
- \skv@err{Key '#1/##1' is not defined}\@ehd
+ \edef\skv@qkeyskvlist{\unexpanded{#3}}%
+ \skvkvnormalize\skv@qkeyskvlist
+ \edef\skv@qkeysfam{\skvtrimspace{#1}}%
+ \def\skv@setqkeys@a##1##2{%
+ \skvifcsdefTF{\skv@qkeysfam/##1/qkeys.cbk}{}{%
+ \skv@err{Key '\skv@qkeysfam/##1'
+ \MessageBreak is not defined}\skv@ehd
}%
\skvifstrcmpTF{##2}\skv@novalue{%
- \skvifcsdefTF{#1/##1/qkeys.def}{%
- \skvcsletcs{#1/##1/qkeys.val}{#1/##1/qkeys.def}%
+ \skvifcsdefTF{\skv@qkeysfam/##1/qkeys.def}{%
+ \skvcsletcs{\skv@qkeysfam/##1/qkeys.val}{\skv@qkeysfam/##1/qkeys.def}%
}{%
\skv@err{No user value and no default
- \MessageBreak for key '#1/##1'}\@ehd
+ \MessageBreak for key '\skv@qkeysfam/##1'}\skv@ehd
}%
}{%
- \skvcsedef{#1/##1/qkeys.val}{\unexpanded{##2}}%
+ \skvcsedef{\skv@qkeysfam/##1/qkeys.val}{\unexpanded{##2}}%
}%
- \skvifcsdefTF{#1/##1/qkeys.chc}{%
- \skvletcs\reserved@a{#1/##1/qkeys.chc}%
- \edef\reserved@b{\skvexpandcsonce{#1/##1/qkeys.val}}%
- \skvxifinTF{,\skvoxdetok\reserved@b,}{,\skvoxdetok\reserved@a,}{}{%
+ \skvletcs\skv@tempval{\skv@qkeysfam/##1/qkeys.val}%
+ \skvletcs\reserved@a{\skv@qkeysfam/##1/qkeys.chc}%
+ \skvifdefTF\reserved@a{%
+ \skvxifinTF{,\detokenize{##2},}{,\skvoxdetok\reserved@a,}{}{%
\skv@err{Value '\detokenize{##2}' for key '##1'
\MessageBreak is not in prescribed list
- \MessageBreak '\skvoxdetok\reserved@a'}\@ehd
+ \MessageBreak '\skvoxdetok\reserved@a'}\skv@ehd
}%
}{}%
- \skvifcsdefTF{#1/##1/qkeys.hp}{%
- \skvletcs\reserved@a{#1/##1/qkeys.hp}%
- \skvcsletcs{\reserved@a##1}{#1/##1/qkeys.val}%
- }{}%
- \skvifcsdefTF{#1/##1/qkeys.arg}{%
- \skvletcs\reserved@a{#1/##1/qkeys.arg}%
+ \skvifcsdefTF{\skv@qkeysfam/##1/qkeys.arg}{%
+ \skvletcs\skv@argpattern{\skv@qkeysfam/##1/qkeys.arg}%
}{%
- \let\reserved@a\skv@simplearg
+ \let\skv@argpattern\skv@simplearg
}%
- \skvletcs\reserved@b{#1/##1/qkeys.cbk}%
+ \skvletcs\skv@callback{\skv@qkeysfam/##1/qkeys.cbk}%
\expandafter\expandafter\expandafter\def\expandafter\expandafter
- \expandafter\reserved@a\expandafter\reserved@a\expandafter
- \quickkeyseov\expandafter{\reserved@b}%
- \expandafter\expandafter\expandafter
- \reserved@a\csname#1/##1/qkeys.val\endcsname\quickkeyseov
+ \expandafter\reserved@a\expandafter\skv@argpattern\expandafter
+ \quickkeyseov\expandafter{\skv@callback}%
+ \expandafter\reserved@a\skv@tempval\quickkeyseov
}%
- \def\skv@setquickkeys@c##1=##2=##3\skv@nil{%
+ \def\skv@setqkeys@b##1=##2=##3\skv@setqkeys@nil{%
\skvxifinTF{,\detokenize{##1},}{,\skvoxdetok\skv@qkeysna,}{}{%
- \skv@setqkeys{##1}{##2}%
+ \skv@setqkeys@a{##1}{##2}%
+ }%
+ }%
+ \skvifcsdefFT{\skv@qkeysfam/qkeys.preset}{}{%
+ \skv@qkeysgetkeynames\skv@qkeyskvlist\skv@qkeyscurrnames
+ \def\skv@setqkeys@c##1=##2=##3\skv@setqkeys@nil{%
+ \skvxifinTF{,\detokenize{##1},}{,\skvoxdetok\skv@qkeyscurrnames,}{}{%
+ \let\skv@setquickkeys@a\skv@bad@setquickkeys@a
+ \skv@setqkeys@b##1={##2}=##3\skv@setqkeys@nil
+ \let\skv@setquickkeys@a\skv@sav@setquickkeys@a
+ }%
+ }%
+ \skvletcs\skv@tempa{\skv@qkeysfam/qkeys.preset}%
+ \skvkvparse*\skv@tempa\skv@tempa{%
+ \expandafter\skv@setqkeys@c\skv@tempa=\skv@novalue=\skv@setqkeys@nil
}%
}%
- \skvdolist*{,}\skv@tempa\skv@tempa{%
- \expandafter\skv@setquickkeys@c\skv@tempa=\skv@novalue=\skv@nil
+ \skvkvparse*\skv@qkeyskvlist\skv@tempa{%
+ \expandafter\skv@setqkeys@b\skv@tempa=\skv@novalue=\skv@setqkeys@nil
}%
\skvrestorestate\skv@setquickkeys\skv@setqkeysdepth
}
+\skvnewlet\skv@sav@setquickkeys@a\skv@setquickkeys@a
+\skvrobustdef*\skv@bad@setquickkeys@a{%
+ \skv@err{'\string\quickkeys.set' can't be nested in a preset
+ \MessageBreak key's callback: this will cause a cyclic call
+ \MessageBreak to '\string\quickkeys.set'}\skv@ehd
+}
% \skvinitializeqkeys{<fam>}[<na>]{<kvlist>}
\skvrobustdef*\skvinitializeqkeys#1{%
@@ -1980,6 +2346,12 @@
% {<no match>}
% \endif
%
+% 1. \skvifcase is expandable but, to simplify the code, \elsedo is mandatory.
+% See \ltsifcases of ltxtools package; it is expandable and the 'else part'
+% can be omitted in it.
+% 2. \skvifcasse and \skvifcases aren't expandable, but \elsedo isn't
+% mandatory.
+%
% Example:
%
% \skvifcase\skvifstrcmpTF{c}
@@ -1989,14 +2361,111 @@
% \elsedo
% no match%
% \endif
+%
+% \skvifcase is expandable.
+%
\skvnewdef\skvifcase#1#2#3\elsedo#4\endif{%
+ % {#2}{#4} represent default action:
\skv@ifcase{#1}{#2}#3{#2}{#4}\skv@casestop
}
\skvnewdef\skv@ifcase#1#2#3{%
- #1{#2}{#3}\skv@ifcase@domatch{\skv@ifcase@a{#1}{#2}}%
+ #1{#2}{#3}{%
+ \skv@ifcase@domatch
+ }{%
+ \skv@ifcase@a{#1}{#2}%
+ }%
}
\skvnewdef\skv@ifcase@a#1#2#3{\skv@ifcase{#1}{#2}}
-\skvnewdef\skv@ifcase@domatch#1#2\skv@casestop{\unexpanded{#1}}
+\skvnewdef\skv@ifcase@domatch#1#2\skv@casestop{\skvtrimspace{#1}}
+
+% \skvifcasse{<teststr>}
+% {<cases>}
+% \elsedo
+% {<no match>}
+% \endif
+%
+% 1. \elsedo can be omitted by the user, ie, it is optional. See also
+% \skvifcases.
+% 2. Because of the need to remove blank spaces before 'case',
+% \skvifcasse isn't expandable.
+%
+% Example:
+%
+% \skvifcasse{x}
+% case{a}{\def\x{do a}}
+% case{b}{\def\x{do b}}
+% case{c}{\def\x{do c}}
+% \elsedo
+% \def\x{no match}
+% \endif
+%
+\skvrobustdef*\skvifcasse#1#2\endif{%
+ \skvxifinTF{\detokenize{\elsedo}}{\detokenize{#2}}{%
+ \begingroup
+ \def\skv@prova##1\elsedo##2\skv@ifcasse@nil{%
+ \endgroup
+ \skv@ifcasse@a{#1}##1case{#1}{##2}\skv@casse@stop
+ }%
+ \skv@prova#2\skv@ifcasse@nil
+ }{%
+ \skv@ifcasse@a{#1}#2case{#1}{}\skv@casse@stop
+ }%
+}
+\skvrobustdef*\skv@ifcasse@a#1{%
+ \@ifnextchar\relax{\skv@ifcasse@b#1}{\skv@ifcasse@b#1}%
+}
+\skvrobustdef*\skv@ifcasse@b#1case#2{%
+ \skvxifstrcmpTF{#1}{#2}{%
+ \skv@ifcasse@domatch
+ }{%
+ \skv@ifcasse@c{#1}%
+ }%
+}
+\skvrobustdef*\skv@ifcasse@c#1#2{\skv@ifcasse@a{#1}}
+\skvrobustdef*\skv@ifcasse@domatch#1#2\skv@casse@stop{\skvtrimspace{#1}}
+
+% \skvifcases<teststr>\then
+% <cases>{<acts>}
+% <default>{<act>}
+% \fi
+%
+% 1. <default>{<act>} can be omitted by the user, ie, it is optional.
+% 2. \skvifcases isn't expandable.
+%
+% Example:
+% \skvifcases x\then
+% case{a}{\def\x{do a}}
+% case{b}{\def\x{do b}}
+% case{c}{\def\x{do c}}
+% default{\def\x{no match}}
+% \fi
+%
+\skvrobustdef*\skvifcases#1\then#2\fi{%
+ % Any space trailing #2 will be absorbed by ##3 of the following
+ % \skv@prova.
+ \begingroup
+ \def\skv@prova##1default##2##3\skv@ifcases@nil{%
+ \endgroup
+ \skvifstrcmpTF{##2}{\@nil}{%
+ \skv@ifcases@a{#1}##1case{#1}{}\skv@cases@stop
+ }{%
+ \skv@ifcases@a{#1}##1case{#1}{##2}\skv@cases@stop
+ }%
+ }%
+ \skv@prova#2default{\@nil}\skv@ifcases@nil
+}
+\skvrobustdef*\skv@ifcases@a#1{%
+ \@ifnextchar\relax{\skv@ifcases@b#1}{\skv@ifcases@b#1}%
+}
+\skvrobustdef*\skv@ifcases@b#1case#2{%
+ \skvxifstrcmpTF{#1}{#2}{%
+ \skv@ifcases@domatch
+ }{%
+ \skv@ifcases@c{#1}%
+ }%
+}
+\skvrobustdef*\skv@ifcases@c#1#2{\skv@ifcases@a{#1}}
+\skvrobustdef*\skv@ifcases@domatch#1#2\skv@cases@stop{#1}
% Evaluating a series of boolean expressions.
%
@@ -2092,17 +2561,18 @@
}
\skvbuildmacrostack\skv@keystate{%
- \do\skv@prefix\do\skvcurrentprefix\do\skv@fams\do\skvcurrentfamily
+ \do\skvcurrentprefix\do\skv@fams\do\skvcurrentfamily
\do\skvcurrentkey\do\skv@header\do\skvcurrentpath\do\skv@na
- \do\skv@naa\do\ifskv@st\do\ifskv@pl\do\ifskv@kf\do\ifskvnovalue
+ \do\skv@currentnames\do\ifskv@st\do\ifskv@pl\do\ifskv@kf\do\ifskvnovalue
\do\skvcurrentvalue\do\CurrentOption\do\ifskv@intry\do\ifskv@success
- \do\ifskv@inpox\do\ifskv@prepo
+ \do\ifskv@inpox\do\ifskv@inprepo\do\skv@pathdo\do\skv@rmkeys
+ \do\ifskv@viarootofsetkeys\do\skv@currpref\do\skv@currfam
}\skv@stackdepthlimit
\skvbuildmacrostack\skv@dirkeys@state{%
- \do\dirkeys@prefixlist\do\dirkeys@familylist\do\dirkeys@holderprefixtoks
+ \do\dirkeys@pathlist\do\dirkeys@holderprefixtoks\do\dirkeys@parser
\do\dirkeys@unknownkeysmacro\do\ifdirkeys@saveunknownkeys
- \do\ifskvindirkeys\do\ifskvdfk@initialize\do\ifskvdfk@saveinitialvalues
+ \do\ifindirectkeys\do\ifskvdfk@initialize\do\ifskvdfk@saveinitialvalues
}\skv@stackdepthlimit
\skvrobustdef\skvappto#1#2{%
@@ -2127,19 +2597,18 @@
}%
}%
}{%
- \skv@err{Token '\detokenize{#3}' is not escaped}\@ehd
+ \skv@err{Token '\detokenize{#3}' is not escaped}\skv@ehd
}%
}
-% \skvaddlist{<parser>}{<listitem>}
-% This is usually called under \edef.
+% \skvaddlist{<parser>}{<listcmd>}
+% This is usually called under \edef. <listcmd> must have been
+% initialized.
\skvnewdef*\skvaddlist#1#2{%
\skvifemptyTF#2{}{\skvexpandonce#2\unexpanded{#1}}%
}
% \skvxaddtolist{<parser>}{<listcmd>}{<newitem>}
-\skvrobustdef\skvxaddtolist#1#2#3{%
- \edef#2{#2\ifx#2\@empty\else#1\fi#3}%
-}
+\skvrobustdef\skvxaddtolist#1#2#3{\edef#2{\skvaddlist#1#2#3}}
% \skvaddtolist[<parser>]{<listcmd>}{<newitem>}
\skvrobustdef*\skvaddtolist{\skv@teststopt{\skv@addtolist{}},}
\skvrobustdef*\skvgaddtolist{\skv@teststopt{\skv@addtolist{\global}},}
@@ -2164,53 +2633,73 @@
}%
}
-% \skvfiltermergelist!<cmd>{<sublist>}<filter>
-% The exclamation mark (!) implies that the outcome is globalized.
-% When there is no filter to be applied, \skvmergelist is faster
-% than \skvfiltermergelist.
-\skvrobustdef*\skvfiltermergelist{\skv@testcl\skv@filtermergelist}
-\skvrobustdef*\skv@filtermergelist#1#2#3{%
+% \skvfiltermergelist![<parser>](<wrapper>)<cmd>{<sublist>}<filter>
+%
+% 1. The exclamation mark (!) implies that the outcome is globalized.
+% 2. When there is no filter to be applied, \skvmergelist is faster
+% than \skvfiltermergelist.
+% 3. <wrapper> will be applied to all the elements (new and old).
+% The default value of <wrapper> is \skvexpandonce.
+% 4. Example:
+% \def\alist{a;b;c}
+% \def\wrap#1{{#1}}
+% \skvfiltermergelist[;](\wrap)\alist{a;d;e}\nofilter
+% \show\alist
+%
+\skvrobustdef*\skvfiltermergelist{%
+ \skv@testcl{\skv@testopt\skv@filtermergelist,}%
+}
+\skvrobustdef*\skv@filtermergelist[#1]{%
+ \skv@testpnopt{\skv@f@ltermergelist{#1}}\skvexpandonce
+}
+\skvrobustdef*\skv@f@ltermergelist#1(#2)#3#4#5{%
\begingroup
- \skv@declarefilter{#3}%
- \skvifdefTF#1{\skvkvnormalize#1}{\def#1{}}%
- \edef\skv@merga{\unexpanded{#2}}%
- \skvkvnormalize\skv@merga
- \skvcommaloop*\skv@merga\skv@merga{%
+ \skv@declarefilter{#5}%
+ \skvifdefTF#3{\skvcsvnormalize[#1]#3}{\def#3{}}%
+ \edef\skv@merga{\unexpanded{#4}}%
+ \skvcsvnormalize[#1]\skv@merga
+ \skvdolist*{#1}\skv@merga\skv@merga{%
\@tempswatrue
\skv@filter\skv@merga\skv@mergb
- \let\skv@mergc#1%
- \let#1\@empty
- \skvcommaloop*\skv@mergc\skv@mergc{%
+ \let\skv@mergc#3%
+ \let#3\@empty
+ \skvdolist*{#1}\skv@mergc\skv@mergc{%
\skv@filter\skv@mergc\skv@mergd
\ifx\skv@mergb\skv@mergd
\@tempswafalse
- \edef#1{\skvaddlist,#1\skvexpandonce\skv@merga}%
+ \edef#3{\skvaddlist#1#3#2{\skv@merga}}%
\else
- \edef#1{\skvaddlist,#1\skvexpandonce\skv@mergc}%
+ \edef#3{\skvaddlist#1#3#2{\skv@mergc}}%
\fi
}%
\if@tempswa
- \edef#1{\skvaddlist,#1\skvexpandonce\skv@merga}%
+ \edef#3{\skvaddlist#1#3#2{\skv@merga}}%
\fi
}%
- \skvaftergroupdef#1\endgroup
- \ifskv@cl\global\let#1#1\fi
+ \skvaftergroupdef#3\endgroup
+ \ifskv@cl\global\let#3#3\fi
}
-% \skvmergelist!<cmd>{<sublist>}
-% The exclamation mark (!) implies that the outcome is globalized.
-\skvrobustdef*\skvmergelist{\skv@testcl\skv@mergelist}
-\skvrobustdef*\skv@mergelist#1#2{%
+% \skvmergelist![<parser>](<wrapper>)<cmd>{<sublist>}
+%
+% 1. The exclamation mark (!) implies that the outcome is globalized.
+% 2. <wrapper> will be applied to only the new elements. The default
+% value of <wrapper> is \skvexpandonce.
+\skvrobustdef*\skvmergelist{\skv@testcl{\skv@testopt\skv@mergelist,}}
+\skvrobustdef*\skv@mergelist[#1]{%
+ \skv@testpnopt{\skv@m@rgelist{#1}}\skvexpandonce
+}
+\skvrobustdef*\skv@m@rgelist#1(#2)#3#4{%
\begingroup
- \skvifdefTF#1{\skvkvnormalize#1}{\def#1{}}%
- \edef\skv@tempa{\unexpanded{#2}}%
- \skvkvnormalize\skv@tempa
- \skvcommaloop*\skv@tempa\skv@tempa{%
- \skvxifinTF{,\skvoxdetok\skv@tempa,}{,\skvoxdetok#1,}{}{%
- \edef#1{\skvaddlist,#1\skvexpandonce\skv@tempa}%
+ \skvifdefTF#3{\skvcsvnormalize[#1]#3}{\def#3{}}%
+ \edef\skv@tempa{\unexpanded{#4}}%
+ \skvcsvnormalize[#1]\skv@tempa
+ \skvdolist*{#1}\skv@tempa\skv@tempa{%
+ \skvxifinTF{#1\skvoxdetok\skv@tempa#1}{#1\skvoxdetok#3#1}{}{%
+ \edef#3{\skvaddlist#1#3#2{\skv@tempa}}%
}%
}%
- \skvaftergroupdef#1\endgroup
- \ifskv@cl\global\let#1#1\fi
+ \skvaftergroupdef#3\endgroup
+ \ifskv@cl\global\let#3#3\fi
}
% \skvfilterremoveelements!<cmd>{<sublist>}<filter>
@@ -2278,15 +2767,20 @@
}
% \skvfilterreplaceelements!<listcmd>{<replacements>}<filter>
+%
% <replacements> => {<old-1>}{<new-1>},...,{<old-n>}{<new-n>}
+%
% An exclamation mark suffix (!) implies that the outcome is globalized.
% When there is no filter to be applied, \skvreplaceelements is only
% negligibly faster than \skvfilterreplaceelements. Hence \skvreplaceelements
% isn't defined in this package. When there is no <filter>, use \nofilter
% as the filter.
+%
% Example:
+%
% \def\cmd{a = 1 , b = 2 , c = 3}
% \skvfilterreplaceelements\cmd{{a = 1}{x = 1},{c = 3}{z=3}}\skv@getkeyname
+%
\skvrobustdef*\skvfilterreplaceelements{%
\skv@testcl\skv@filterreplaceelements
}
@@ -2322,44 +2816,61 @@
\skvaftergroupdef#1\endgroup
\ifskv@cl\global\let#1#1\fi
}
+\skvnewdef*\skvcurrentfullkey{\skv@header\skvcurrentkey}
+\skvnewlet\skvcurrenttriple\skvcurrentfullkey
+\skvrobustdef*\skvsetdefaultprefix#1{%
+ \edef\skvdefaultprefix{\skvtrimspace{#1}}%
+ \let\skv@defapf\skvdefaultprefix
+}
+\skvsetdefaultprefix{KV}
\skvrobustdef*\skv@makeprefix#1{%
% It is required to first fully expand the prefix:
\edef\skvcurrentprefix{#1}%
\skvdespacecontent\skvcurrentprefix
- \edef\skv@prefix{%
- \ifx\skvcurrentprefix\@empty\else\skvcurrentprefix/\fi
- }%
}
+% \skv@makeheader{<family>}
\skvrobustdef*\skv@makeheader#1{%
% Fully expand the family, in case it is given as \skvcurrentfamily or
% a local/temporary macro:
\edef\skvcurrentfamily{#1}%
\skvdespacecontent\skvcurrentfamily
- \edef\skvcurrentpath{\skv@prefix\skvcurrentfamily}%
+ \ifx\skvcurrentprefix\@undefined
+ \let\skvcurrentprefix\skvdefaultprefix
+ \fi
\edef\skv@header{%
- \skv@prefix\ifx\skvcurrentfamily\@empty\else\skvcurrentfamily/\fi
+ \ifx\skvcurrentprefix\@empty\else\skvcurrentprefix/\fi
+ \ifx\skvcurrentfamily\@empty\else\skvcurrentfamily/\fi
}%
+ \ifx\skv@header\@empty
+ \def\skv@header{/}%
+ \let\skvcurrentpath\skv@header
+ \else
+ \def\reserved@a##1/\@nil{##1}%
+ \edef\skvcurrentpath{\expandafter\reserved@a\skv@header\@nil}%
+ \ifx\skvcurrentpath\@empty
+ \def\skvcurrentpath{/}%
+ \fi
+ \fi
}
-\skvrobustdef*\skvdefaultprefix#1{\edef\skv@defaultpref{#1}}
-\skvdefaultprefix{KV}
\skvrobustdef*\skv@testopta#1{%
\skvifstar
- {\skv@sttrue\skv@t@stopta{#1}}{\skv@stfalse\skv@t@stopta{#1}}%
+ {\skv@sttrue\skv@t@stopta{#1}}
+ {\skv@stfalse\skv@t@stopta{#1}}%
}
\skvrobustdef*\skv@t@stopta#1{\skvifplus{\skv@pltrue#1}{\skv@plfalse#1}}
\skvrobustdef*\skv@testoptb#1{%
- \skv@testopt{\skv@t@stoptb{#1}}\skv@defaultpref
+ \skv@testopt{\skv@t@stoptb{#1}}\skvdefaultprefix
}
\skvrobustdef*\skv@t@stoptb#1[#2]#3{%
\skv@makeprefix{#2}\skv@makeheader{#3}#1%
}
\skvrobustdef*\skv@testoptc#1{%
- \skv@testopt{\skv@t@stoptc{#1}}\skv@defaultpref
+ \skv@testopt{\skv@t@stoptc{#1}}\skvdefaultprefix
}
\skvrobustdef*\skv@t@stoptc#1[#2]#3{%
\skvxifinTF{,}{\detokenize{#2}}{%
\skv@err{Only one prefix is allowed here,
- \MessageBreak but you gave '#2'}\@ehd
+ \MessageBreak but you gave '#2'}\skv@ehd
}{%
\skv@makeprefix{#2}%
\edef\skv@fams{#3}%
@@ -2384,43 +2895,51 @@
\skvifnextchar[{\skv@sttrue#1{#2}{#3}}{\skv@stfalse#1{#2}{#3}[]}%
}
\skvrobustdef*\skv@getkeyname#1#2{%
- \expandafter\skv@g@tkeyname#1=\skv@nil#2%
+ \expandafter\skv@g@tkeyname#1=\skv@getname@nil#2%
}
-\skvrobustdef*\skv@g@tkeyname#1=#2\skv@nil#3{%
- \skv@strippointers{#1}\skvcurrentkey
+\skvrobustdef*\skv@g@tkeyname#1=#2\skv@getname@nil#3{%
+ \skv@strippointersfromkey{#1}%
\let#3=\skvcurrentkey
}
-
-% #1=key-value pairs; #2=result macro
-\skvrobustdef*\skv@getkeynames#1#2{%
+\skvrobustdef*\skv@getkeyvalue#1#2{%
+ \expandafter\skv@g@tkeyvalue#1==\skv@getvalue@nil#2%
+}
+\skvrobustdef*\skv@g@tkeyvalue#1={\skv@g@tk@yvalue#1=.}
+\skvrobustdef*\skv@g@tk@yvalue#1=#2=#3\skv@getvalue@nil#4{%
+ \edef#4{\unexpanded\expandafter{\@gobble#2}}%
+ \skvexpbracenext\skvifbracedTF#4{%
+ \skvvaluebracedtrue
+ }{%
+ \skvvaluebracedfalse
+ \skvexpbracenext\skv@strippointersfromvalue#4%
+ }%
+ \let#4=\skvcurrentvalue
+}
+% \skv@getnamesofkeys{<kv list>}{<result macro>}
+\skvrobustdef*\skv@getnamesofkeys#1#2{%
\begingroup
\edef\skv@prova{\unexpanded{#1}}%
\skvkvnormalize\skv@prova
\let#2\@empty
\skvcommaloop*\skv@prova\skv@prova{%
- \expandafter\expandafter\expandafter
- \skv@g@tkeyname\skv@prova=\skv@nil\skv@prova
- \skvaddtolist*#2\skv@prova
+ \expandafter\skv@g@tkeyname\skv@prova=\skv@getname@nil\skv@prova
+ \edef#2{\skvaddlist,#2\skvexpandonce\skv@prova}%
}%
\skvaftergroupdef#2\endgroup
}
\skvnewdef*\skv@badkeynames{}
\skvnewdef*\skvaddbadkeynames{\skvappendtomacro\skv@badkeynames}
-\skvnewdef\skvcurrenttriple{%
- \skvcurrentprefix/\skvcurrentfamily/\skvcurrentkey
-}
\skvrobustdef*\skv@definedefault#1#2{%
\ifskv@inoptionsec\else
\skvxifinTF{,\skvcurrentprefix,}{,skv,SKV,}{%
\skvxifinTF{,\skvcurrentfamily,}{,skeyval,}{%
- \skv@err{Prefix/family '\skvcurrentprefix/\skvcurrentfamily'
- are reserved}\@ehd
+ \skv@err{Prefix/family '\skvcurrentpath' are reserved}\skv@ehd
}{}%
}{}%
\fi
\ifskv@tracingkeys
\skvxifinTF{,#1,}{,\skv@badkeynames,}{%
- \skv@err{Key name '#1' not allowed}\@ehd
+ \skv@err{Key name '#1' not allowed}\skv@ehd
}{}%
\fi
\skvcsedef{\skv@header#1.@defa}{%
@@ -2444,102 +2963,173 @@
% create 'needini' lists of families.
\skvrobustdef*\skv@recordkey#1#2{%
\begingroup
- \skvifcsdefFT{\skv@header.@needini}{%
+ \skvifcsdefFT{\skvcurrentpath.@needini}{%
\endgroup\skv@swafalse
}{%
\skv@swatrue
- \skvxifinTF{,#1,}{,\skvexpandcsonce{\skv@header.@needini},}{%
+ \skvxifinTF{,#1,}{,\skvexpandcsonce{\skvcurrentpath.@needini},}{%
\edef\skv@tempa{\skvtrimspace{#2}}%
\edef\skv@tempa{%
#1=\skvoifstrcmpTF{\skv@tempa}{true}{false}{\skvexpandonce\skv@tempa}%
}%
- \skvletcs\skv@tempb{\skv@header.@inikv}%
+ \skvletcs\skv@tempb{\skvcurrentpath.@inikv}%
\skvifdefTF\skv@tempb{%
\skvxifinTF{,\skvoxdetok\skv@tempa,}{,\skvoxdetok\skv@tempb,}{}{%
- \skvcsedef{\skv@header.@inikv}{%
+ \skvcsedef{\skvcurrentpath.@inikv}{%
\skvaddlist,\skv@tempb\skvexpandonce\skv@tempa
}%
}%
}{%
- \skvcsedef{\skv@header.@inikv}{\skvexpandonce\skv@tempa}%
+ \skvcsedef{\skvcurrentpath.@inikv}{\skvexpandonce\skv@tempa}%
}%
}{}%
}%
\ifskv@swa
\expandafter\skvaftergroupdef\csname
- \skv@header.@inikv\expandafter\endcsname
+ \skvcurrentpath.@inikv\expandafter\endcsname
\expandafter\endgroup
\fi
}
% Key will be given in the form <pointer>{<key>}. The command
-% \skv@strippointers is called both when defining and setting keys. When
-% setting keys, we also call \skv@replacepointers to replace .usevalue
-% pointer with the value of the key.
+% \skv@strippointersfromkey is called both when defining and setting keys.
%
% Notes:
-% 1. The pointer \savevalue (of ltxkeys package) or .save value is
-% not used in the skeyval package, since the key's value is
+% 1. When setting keys, we also call \skv@replacepointers to replace
+% '.use value' pointer with the value of the key.
+% 2. There is no pointer '.save value', since the key's value is
% always saved automatically.
%
-\skvrobustdef*\skv@strippointers#1#2{%
+% \skv@strippointersfromkey{<key name>}
+% \skv@strippointersfromkey*{<key name cmd>}
+%
+% Return \skvcurrentkey.
+%
+\skvrobustdef*\skv@strippointersfromkey{%
+ \skv@i@testst\skv@str@ppointersfromkey
+}
+\skvrobustdef*\skv@str@ppointersfromkey#1{%
\begingroup
- \edef#2{%
- \skvifstrcmpTF{#1}{\skvcurrentkey}
- {\skvcurrentkey}{\skvtrimspace{#1}}%
- }%
- \def\skv@prova{\expandafter\skv@findpointer\expandafter}%
- % We can't use #1 in place of #2 in the following, since
- % #2 may have had some pointers stripped in the last call
- % to \skv@findpointer. Also, we can't \edef #2 here, since
- % after each call to \skv@findpointer, we want to use the latest
- % meaning of #2.
- \def\do{}%
- \def\skv@add##1{%
- \edef\do{\skvexpandonce\do\unexpanded{##1}}%
- }%
- \skv@prova{#2}{.need value}#2{%
- \skv@add{\skvcsdef{\skv@header#2.@ndv}{00}}%
- }{%
- \skv@prova{#2}{.forbid value}#2{%
- \skv@add{\skvcsdef{\skv@header#2.@fbv}{00}}%
+ \toks@{}%
+ \skv@usetempst{#1}\skv@tempa
+ % We can choose to ignore the search for pointers where we don't
+ % use pointers. This is useful at least in one respect: during debugging
+ % in non-pointer circumstances. In general, it is not advisable to ignore
+ % pointers.
+ \ifskv@ignorepointers\else
+ \def\skv@tempb{\expandafter\skv@findpointer\expandafter{\skv@tempa}}%
+ \def\skv@add##1{\edef\x{\toks@{\the\toks@##1}}\x}%
+ \skv@tempb{.need value}\skv@tempa{%
+ \skv@add{\skvcsdef{\skv@header\skv@tempa.@ndv}{}}%
}{%
- \skv@prova{#2}{.expanded}#2{%
- \edef#2{#2}%
+ \skv@tempb{.gneed value}\skv@tempa{%
+ \skv@add{\skvcsgdef{\skv@header\skv@tempa.@ndv}{}}%
}{%
- \skv@prova{#2}{.expand once}#2{%
- \edef#2{\skvexpandtwice{#2}}%
+ \skv@tempb{.forbid value}\skv@tempa{%
+ \skv@add{\skvcsdef{\skv@header\skv@tempa.@fbv}{}}%
}{%
- \skv@prova{#2}{.expand twice}#2{%
- \edef#2{\skvexpandthrice{#2}}%
+ \skv@tempb{.gforbid value}\skv@tempa{%
+ \skv@add{\skvcsgdef{\skv@header\skv@tempa.@fbv}{}}%
}{}%
}%
}%
}%
+ \fi
+ \skvexpanded{\endgroup
+ \the\toks@
+ % The following complication is because of, e.g., pntkeys:
+ \edef\noexpand\skvcurrentkey{%
+ \noexpand\unexpanded{\skvexpandonce\skv@tempa}%
+ }%
}%
- \skvexpanded{\endgroup\skvcmdexit#2\do}%
}
-\skvrobustdef*\skv@findpointer#1#2#3{%
+% \skv@strippointersfromvalue{<key value>}
+% \skv@strippointersfromvalue*{<key value cmd>}
+%
+% Return \skvcurrentvalue.
+%
+\skvrobustdef*\skv@strippointersfromvalue{%
+ \skv@i@testst\skv@str@ppointersfromvalue
+}
+\skvrobustdef*\skv@str@ppointersfromvalue#1{%
\begingroup
- \def\skv@prova##1#2##2##3\pointer@nil{%
- \endgroup
+ \skv@usetempst{#1}\skv@tempa
+ \ifskv@ignorepointers\else
+ \def\skv@tempb{\expandafter\skv@findpointer\expandafter{\skv@tempa}}%
+ % The following order is important, since '.expand' will match
+ % '.expand once' and erroneously give the key's value as 'o'.
+ \skv@tempb{.expand once process list}\skv@tempa{%
+ \skv@processvalueaslisttrue
+ \edef\skv@tempa{\skvexpandtwice\skv@tempa}%
+ }{%
+ \skv@tempb{.expand twice process list}\skv@tempa{%
+ \skv@processvalueaslisttrue
+ \edef\skv@tempa{\skvexpandthrice\skv@tempa}%
+ }{%
+ \skv@tempb{.expand process list}\skv@tempa{%
+ \skv@processvalueaslisttrue
+ \edef\skv@tempa{\skv@tempa}%
+ }{%
+ \skv@tempb{.eprocess list}\skv@tempa{%
+ \skv@processvalueaslisttrue
+ \edef\skv@tempa{\skv@tempa}%
+ }{%
+ \skv@tempb{.process list}\skv@tempa{%
+ \skv@processvalueaslisttrue
+ }{%
+ \skv@tempb{.expand once}\skv@tempa{%
+ \edef\skv@tempa{\skvexpandtwice\skv@tempa}%
+ }{%
+ \skv@tempb{.expand twice}\skv@tempa{%
+ \edef\skv@tempa{\skvexpandthrice\skv@tempa}%
+ }{%
+ \skv@tempb{.expanded}\skv@tempa{%
+ \edef\skv@tempa{\skv@tempa}%
+ }{%
+ \skv@tempb{.expand}\skv@tempa{%
+ \edef\skv@tempa{\skv@tempa}%
+ }{}%
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+ \fi
+ \let\skvcurrentvalue\skv@tempa
+ \skvexpanded{\endgroup
+ \skvcmdexit\skvcurrentvalue
+ \skvboolexit\ifskv@processvalueaslist
+ }%
+}
+\skvrobustdef*\skv@findpointer#1#2#3{%
+ \def\skv@f@ndpointer##1#2##2##3\skv@pointer@nil{%
\skvifstrcmpTF{##2}{\skv@nil}{%
\@secondoftwo
}{%
- \skviflacus##1\then\else
+ % We don't want, eg, '<tokens>.expanded{value}', since in this case
+ % applying \edef to the value macro may be unsafe on <tokens>:
+ \skvifblankTF{##1}{}{%
\skv@err{Nothing should come before the
- \MessageBreak pointer '#2' on key '##2'}\@ehd
- \fi
+ \MessageBreak pointer '#2' on key '##2'.
+ \MessageBreak If you require the value of the key to be expanded,
+ \MessageBreak you should have done the expansion yourself}\skv@ehd
+ }%
\edef#3{\skvtrimspace{##2}}%
\@firstoftwo
}%
}%
- \skv@prova#1#2{\skv@nil}\pointer@nil
+ \skv@f@ndpointer#1#2{\skv@nil}\skv@pointer@nil
}
-
-% Extract pseudo key name from a weird key name of the form
-% 'evaluate (\x) as (\y) using (\numexpr\x*2)':
-\skvrobustdef*\skv@extractpntkey#1#2{%
+% \skv@extractpntkey@atdefkey{<toks>}{<cmd>}
+%
+% At define key, extract pseudo key name from a weird key name of the form
+%
+% evaluate (?) as (?) using (?)
+%
+\skvrobustdef*\skv@extractpntkey@atdefkey#1#2{%
\begingroup
\@tempcnta\skvz@
\def#2{}%
@@ -2552,44 +3142,44 @@
\fi
}%
\skv@prova#1(\@nil)%
- \in@false
\ifx#2\@empty
\edef#2{\unexpanded{#1}}%
\else
- \skvifstreq{#2}{\skvcurrentkey}\then
- \in@true
- % The number of arguments of the pseudo key is determined by the
- % number of closed parentheses:
- \skvcsedef{\skv@header#2.@x0arg}{%
- \skvgenerateparameters{1}\@tempcnta
- }%
- \fi
+ % The number of arguments of the pseudo key is determined by the
+ % number of closed parentheses:
+ \skvcsedef{\skv@header#2.@x0arg}{\skvgenerateparameters{1}\@tempcnta}%
\fi
\skvexpanded{\endgroup
\skvcmdexit#2%
- \ifin@
- \expandafter\skvcmdexit\csname\skv@header#2.@x0arg\endcsname
- \fi
+ \skvcsexit{\skv@header#2.@x0arg}%
}%
}
-\skvrobustdef*\skv@extr@ctpntkey#1#2#3{%
+% \skv@extractpntkey@atsetkey{<toks>}
+%
+% At set key, extract pseudo key name from a weird key name of the form
+%
+% evaluate (?) as (?) using (?)
+%
+\skvrobustdef*\skv@extractpntkey@atsetkey#1{%
\begingroup
- \let\skv@tvalue#3%
- \def#2{}\def#3{}%
+ \def\skvcurrentkey{}%
+ \def\skvcurrentvalue{}%
\def\skv@prova##1(##2){%
\def\skv@provb{##2}%
\ifx\skv@provb\@nnil\else
- \edef#2{\skvexpandonce#2\skvtrimspace{##1}}%
- \edef#3{\skvexpandonce#3{\skvtrimspace{##2}}}%
+ \edef\skvcurrentkey{\skvxonce\skvcurrentkey\skvtrimspace{##1}}%
+ \edef\skvcurrentvalue{\skvxonce\skvcurrentvalue{\skvtrimspace{##2}}}%
\expandafter\skv@prova
\fi
}%
\skv@prova#1(\@nil)%
- \ifx#2\@empty
- \edef#2{\unexpanded{#1}}%
- \let#3\skv@tvalue
+ \ifx\skvcurrentkey\@empty
+ \skv@err{No key name for a parenthesized key}\skv@ehd
+ \expandafter\@nodocument
\fi
- \skvexpanded{\endgroup\skvcmdexit#2\skvcmdexit#3}%
+ \skvexpanded{\endgroup
+ \skvcmdexit\skvcurrentkey\skvcmdexit\skvcurrentvalue
+ }%
}
\skvrobustdef*\skv@replacepointers#1{%
\begingroup
@@ -2602,33 +3192,30 @@
}%
\skvaftergroupdef\skvcurrentvalue\endgroup
}
-% In xkeyval package, if we put, eg,
+% In the following scheme, if we have, eg,
%
-% key2=\dimexpr\usevalue{key1}*5\relax
+% key2=\dimexpr.use value{key1}*5\relax
%
-% \dimexpr will be lost (as part of the value of key2) in pointer
-% replacement. We avoid that deficiency here.
+% \dimexpr will be retained as part of the value of key2 in pointer
+% replacement.
%
\skvrobustdef*\skv@r@placepointers#1.use value#2{%
+ % In case #1 isn't empty:
+ \edef\skvcurrentvalue{\skvexpandonce\skvcurrentvalue\unexpanded{#1}}%
\edef\skv@prova{\unexpanded{#2}}%
- \skvifxTF\skv@prova\skv@nnil{%
- \edef\skvcurrentvalue{\unexpanded{#1}}%
- }{%
+ \skvifxTF\skv@prova\skv@nnil{}{%
\skvifcsdefFT{\skv@header#2.@value}{%
- \skv@err{No value recorded for key '#2'; ignored}\@ehd
+ \skv@err{No value recorded for key '#2'; ignored}\skv@ehd
\skv@r@placepointers
}{%
\skvxifinTF{,\detokenize{#2},}{,\skvoxdetok\skv@tempa,}{%
\skv@err{Back linking of pointers;
- \MessageBreak pointer replacement canceled}\@ehd
+ \MessageBreak pointer replacement canceled}\skv@ehd
}{%
\edef\skv@tempa{\skvaddlist,\skv@tempa\unexpanded{#2}}%
- \edef\skv@prova{\skvexpandcsonce{\skv@header#2.@value}}%
- \skvexpandbracenext\skvifbracedTF\skv@prova{%
- \skvexpandbracenext{\skv@r@placepointers#1}\skv@prova
- }{%
- \skvexpandnext{\skv@r@placepointers#1}\skv@prova
- }%
+ \skvletcs\skv@prova{\skv@header#2.@value}%
+ \skvexpbracenext\skvifbracedTF\skv@prova\skvexpbracenext\skvexpandnext
+ \skv@r@placepointers\skv@prova
}%
}%
}%
@@ -2638,9 +3225,7 @@
%
% \skvassignargs[<prefixes>]{<families>}[<expansion.type>]{<keys>}{<arg>}
%
-% 1. Valid expansion types are x0 (unexpanded), x1 (expand once),
-% x2 (expand twice), xx (expand fully). The default expansion type is
-% x0 (unexpanded).
+% 1. Valid expansion types are .expand once, .expand twice, .expanded.
% 2. At set keys (not at define keys), the argument to the listed keys will
% be expanded using the expansion type.
% 3. The argument will be assigned whether or not a key already has been
@@ -2651,74 +3236,202 @@
%
% Example:
%
-% \skvassignargs[KV1,KV2]{fam1,fam2}[x1]{keya,keyb}{#1/#2}
+% \skvassignargs[KV1,KV2]{fam1,fam2}[.expand once]{keya,keyb}{#1/#2}
+%
+% The keys could then be set as
+%
% \skvsetkeys[KV1]{fam2}{keya=vala/valb}
%
% For each prefix and family, this will define parameterless functions
%
-% \<prefix>/<family>/key/.@x1arg.
+% \<prefix>/<family>/<key>.@x1arg.
%
% which will be used at setkeys to define and execute the key's callback.
%
-\skvrobustdef*\skvassignargs{\skv@testopt\skv@assignargs\skv@defaultpref}
+\skvrobustdef*\skvassignargs{\skv@testopt\skv@assignargs\skvdefaultprefix}
\skvrobustdef*\skv@assignargs[#1]#2{%
\begingroup
\skv@testopt{\skv@assignargs@a{#1}{#2}}{^skv^}%
}
\skvrobustdef*\skv@assignargs@a#1#2[#3]#4#5{%
- \edef\skv@tempc{\skvtrimspace{#5}}%
- \def\skv@tempd{}%
+ \edef\skv@tempb{\skvtrimspace{#5}}%
+ \def\skv@tempc{}%
\skvifstrcmpTF{#3}{^skv^}{%
\def\skvexpander{x0}%
}{%
- \skv@checkexpander{#3}%
- \edef\skvexpander{\skvtrimspace{#3}}%
+ \skv@getexpander@a{#3}\skvexpander
}%
- \def\\{\noexpand\unexpanded}%
- \skvcommaloop{#1}\skv@tempa{%
+ \skvcommaparse{#1}\skv@tempa{%
\skv@makeprefix\skv@tempa
- \skvcommaloop{#2}\skv@tempa{%
+ \skvcommaparse{#2}\skv@tempa{%
\skv@makeheader\skv@tempa
\skvcommaparse{#4}\skv@tempa{%
- \edef\skv@tempd{\skvexpandonce\skv@tempd
+ \edef\skv@tempc{%
+ \skvexpandonce\skv@tempc
\skvcsedef{\skv@header\skv@tempa.@\skvexpander arg}{%
- \\{\\{\skvexpandonce\skv@tempc}}%
+ \noexpand\unexpanded{\skvexpandonce\skv@tempb}%
}%
}%
}%
}%
}%
- \skvexpanded{\endgroup\skv@tempd}%
+ \expandafter\endgroup\skv@tempc
}
-\skvrobustdef*\skv@checkexpander#1{%
- \skvxifinTF{,\expandafter\skvtrimspace\expandafter
- {\detokenize\expandafter{#1}},}{,\detokenize{x0,x1,x2,xx},}{}{%
- \skv@err{Illegal expansion type '#1'}\@ehd
+
+% \skv@getexpander@a{<expander.type>}{<return.cmd>}
+%
+% 1. <return.cmd> will contain one of 'x0', 'x1', 'x2', 'xx', which will be
+% saved in a key-dependent macro that represents the key's argument.
+%
+\skvrobustdef*\skv@getexpander@a#1#2{%
+ \begingroup
+ \edef\skv@prova{\skvotrimspace{#1}}%
+ \def\skv@provb##1{%
+ \def\skv@provb####1##1####2####3\skv@nil{%
+ \endgroup
+ \def#2{####2}%
+ \ifx#2\@nnil
+ \skv@err{Unknown expansion type '\detokenize{##1}'}\skv@ehd
+ \fi
+ }%
+ \skv@provb .expand once{x1},.expand twice{x2},.expanded{xx},%
+ .expand{xx},##1{\@nil}\skv@nil
}%
+ \expandafter\skv@provb\expandafter{\skv@prova}%
}
-
-% Ordinary keys:
+% \skv@getexpander@b{<expander.type>}
+%
+% 1. <expander.type> is one of 'x0', 'x1', 'x2', 'xx', which had been
+% saved in a key-dependent macro.
+%
+% 2. \skv@getexpander@b returns macro \skvexpander, which will
+% contain one of \unexpanded, \skvexpandonce, \skvexpandtwice, \@iden.
+%
+\skvrobustdef*\skv@getexpander@b#1{%
+ \begingroup
+ \edef\skv@prova{\skvtrimspace{#1}}%
+ \def\skv@provb##1{%
+ \def\skv@provb####1##1####2####3\skv@nil{%
+ \endgroup
+ \def\skvexpander{####2}%
+ \ifx\skvexpander\@nnil
+ \skv@err{Unknown expansion type '\detokenize{##1}'}\skv@ehd
+ \fi
+ }%
+ \skv@provb x0{\unexpanded},x1{\skvexpandonce},x2{\skvexpandtwice},%
+ xx{\@iden},##1{\@nil}\skv@nil
+ }%
+ \expandafter\skv@provb\expandafter{\skv@prova}%
+}
+% \skv@getargpattern{<callback token list>}
+%
+% Get argument type from the key's callback. The valid tags are
+%
+% .arg, .arg unexpanded, .arg expanded, .arg expand, .arg expand once,
+% .arg expand twice.
+%
+\skvrobustdef*\skv@getargpattern{%
+ \let\skv@argpattern\@undefined
+ \def\do##1##2{%
+ \ifx\do##1\else
+ \skvxifinTF{\detokenize{##1}}{\skvoxdetok\skv@callback}{%
+ \def\skv@prova####1##1####2####3\skv@argpattern@nil{%
+ \edef\skv@argpattern{\unexpanded{####2}}%
+ \ifx\skv@argpattern\@empty
+ \let\skv@argpattern\skv@simplearg
+ \fi
+ \edef\skv@callback{\skvtrimspace{####1}\skvtrimspace{####3}}%
+ }%
+ \expandafter\skv@prova\skv@callback\skv@argpattern@nil
+ \def\skvexpandertype{##2}%
+ \def\do####1\do\do{}%
+ }{}%
+ \expandafter\do
+ \fi
+ }%
+ % The following order is important, to avoid incorrect match
+ % of the search term:
+ \do{.arg unexpanded}{x0}{.arg expand once}{x1}{.arg expand twice}{x2}%
+ {.arg expanded}{xx}{.arg expand}{xx}{.arg}{x0}\do\do
+ \ifdefined\skv@argpattern\else
+ % Argument pattern might have been specified outside the key's
+ % callback.
+ \def\do##1{%
+ \ifx\do##1\else
+ \skvifnamedefTF{\skvcurrentfullkey.@##1arg}{%
+ \skvletcs\skv@argpattern{\skvcurrentfullkey.@##1arg}%
+ \def\skvexpandertype{##1}%
+ \def\do####1\do{}%
+ }{}%
+ \expandafter\do
+ \fi
+ }%
+ \do{xx}{x2}{x1}{x0}\do
+ \fi
+ \ifdefined\skv@argpattern
+ % Possibly expand value:
+ \skvstripouterbraces{2}\skv@argpattern
+ \def\do##1##2{%
+ \ifx\do##1\else
+ \skvxifstrcmpTF{##2}\skvexpandertype{%
+ \edef\skvcurrentvalue{%
+ \expandafter##1\expandafter{\skvcurrentvalue}%
+ }%
+ \def\do####1\do\do{}%
+ }{}%
+ \expandafter\do
+ \fi
+ }%
+ \do\@iden{xx}\skvexpandtwice{x2}\skvexpandonce{x1}\unexpanded{x0}\do\do
+ \else
+ \let\skv@argpattern\skv@simplearg
+ \fi
+}
+% +++++++++++++ Ordinary keys:
%
% \skvordkey[<pref>]{<fam>}{<key>}[<defa>]{<callback>}
%
-\skvrobustdef*\skvordkey{\skv@testoptb\skv@ordkey}
-\skvrobustdef*\skv@ordkey#1{%
- \skv@strippointers{#1}\skvcurrentkey
- \skvexpanded{\skv@testopt{\skv@ordkey@a{\skvcurrentkey}}{^skv^}}%
+\skvrobustdef*\skvordkey{\skv@testoptb{\skv@ordkey{e}}}
+\skvrobustdef*\skvordkeys{\skv@testoptb{\skv@ordkeys{e}}}
+%
+% \skvgordkey[<pref>]{<fam>}{<key>}[<defa>]{<callback>}
+%
+% Global ordinary keys. So far, these are needed only by \skvgdisablekey.
+%
+\skvrobustdef*\skvgordkey{\skv@testoptb{\skv@ordkey{x}}}
+\skvrobustdef*\skvgordkeys{\skv@testoptb{\skv@ordkeys{x}}}
+\skvrobustdef*\skv@ordkey#1#2{%
+ \skv@strippointersfromkey{#2}%
+ \skvexpanded{\skv@testopt{\skv@ordkey@a{#1}{\skvcurrentkey}}{^skv^}}%
}
-\skvrobustdef*\skv@ordkey@a#1[#2]#3{%
- \skvifstrcmpTF{#2}{^skv^}{}{\skv@definedefault{#1}{#2}}%
- \skvcsedef{\skv@header#1.@cbk}{\unexpanded{#3}}%
+\skvrobustdef*\skv@ordkey@a#1#2[#3]#4{%
+ \skvifstrcmpTF{#3}{^skv^}{}{\skv@definedefault{#2}{#3}}%
+ % The pointer '.hp' may be used to set a holder prefix for the key.
+ \skvxifinTF{\detokenize{.hp}}{\detokenize{#4}}{%
+ \def\skv@prova##1.hp##2##3\skv@ord@nil{%
+ \let\skv@gobble@or@iden\@iden
+ \edef\skv@hp{\unexpanded{##2}}%
+ \edef\skv@callback{\unexpanded{##1##3}}%
+ }%
+ \skv@prova#4\skv@ord@nil
+ }{%
+ \let\skv@gobble@or@iden\@gobble
+ \edef\skv@callback{\unexpanded{#4}}%
+ }%
+ \csname skvcs#1def\endcsname{\skv@header#2.@cbk}{%
+ % This can be called in #3 access the value of ordinary key.
+ % No prefix is used here, to reduce macro name:
+ \skv@gobble@or@iden{\skvcslet{\skv@hp#2}\noexpand\skvcurrentvalue}%
+ \skvexpandonce\skv@callback
+ }%
}
-\skvrobustdef*\skvordkeys{\skv@testoptb\skv@ordkeys}
-\skvrobustdef*\skv@ordkeys#1{\skv@testopt{\skv@ordkeys@a{#1}}{^skv^}}
-\skvrobustdef*\skv@ordkeys@a#1[#2]#3{%
- \skvcommaparse{#1}\skv@tempa{%
- \skvexpbracenext\skv@strippointers\skv@tempa\skvcurrentkey
- \skvexpanded{\skv@ordkey@a{\skvcurrentkey}}[#2]{#3}%
+\skvrobustdef*\skv@ordkeys#1#2{\skv@testopt{\skv@ordkeys@a{#1}{#2}}{^skv^}}
+\skvrobustdef*\skv@ordkeys@a#1#2[#3]#4{%
+ \skvcommaparse{#2}\skv@prova{%
+ \skvexpbracenext\skv@strippointersfromkey\skv@prova
+ \skvexpbracenext{\skv@ordkey@a{#1}}\skvcurrentkey[#3]{#4}%
}%
}
-
% \skvvoidkey[<pref>]{<fam>}{<key>}[<defa>]{<callback>}
%
% A void key is an invalid key. A user who tries to set that key will
@@ -2727,20 +3440,47 @@
%
\skvrobustdef*\skvvoidkey{\skv@testoptb\skv@voidkey}
\skvrobustdef*\skv@voidkey#1{%
- \skv@strippointers{#1}\skvcurrentkey
+ \skv@strippointersfromkey{#1}%
\skvexpanded{\skv@testopt{\skv@voidkey@a{\skvcurrentkey}}{^skv^}}%
}
\skvrobustdef*\skv@voidkey@a#1[#2]#3{%
\skvifstrcmpTF{#2}{^skv^}{}{\skv@definedefault{#1}{#2}}%
- % Simply inserting '#3' in the next definition will not work because
- % of the possible parameter characters in #3:
- \edef\skv@tempa##1##2{%
- ##2%
- \skv@err{Key '#1' of family '\skvcurrentprefix/\skvcurrentfamily'
- \MessageBreak has been set invalid by its author}\noexpand\@ehd
+ \skvcsedef{\skv@header#1.@cbk}{%
+ \unexpanded{#3}\relax
+ \skv@err{Key '#1' of family '\skvcurrentpath'
+ \MessageBreak has been set invalid by its author}\noexpand\skv@ehd
+ }%
+}
+% \skvobsoletekey
+% [<pref>]{<fam>}{<obsolete key>}{<new key>}[<defa>]{<callback>}
+%
+% 1. An obsolete key is a key that is no longer in use and has
+% been replaced by a new key. A user who tries to set an obsolete
+% key will automatically be told that the key is obsolete and that
+% he/she should instead use the new key.
+% 2. The author of an obsolete key can also use <callback> to set a
+% message for the user. <callback> can be empty.
+% 3. Pointers can be used on both <obsolete key> and <new key>.
+%
+\skvrobustdef*\skvobsoletekey{\skv@testoptb\skv@obsoletekey}
+\skvrobustdef*\skv@obsoletekey#1#2{%
+ \skv@strippointersfromkey{#1}%
+ \skvexpanded{%
+ \skv@testopt{\skv@obsoletekey@a{\skvcurrentkey}{#2}}{^skv^}%
+ }%
+}
+\skvrobustdef*\skv@obsoletekey@a#1#2[#3]#4{%
+ \skvifstrcmpTF{#3}{^skv^}{}{\skv@definedefault{#1}{#3}}%
+ \skvcsedef{\skv@header#1.@cbk}{%
+ \unexpanded{#4}\relax
+ \noexpand\skv@warn{Key '\skvcurrentpath/#1'
+ \MessageBreak is now obsolete. Instead of using the obsolete
+ \MessageBreak key '#1', I will now set the new key
+ \MessageBreak '#2' with the value you have given for
+ \MessageBreak key '#1'. You can avoid this warning by
+ \MessageBreak using the new key '#2' instead of the
+ \MessageBreak obsolete key '#1'}\noexpand\skv@ehd
}%
- \skv@toksa\expandafter{\skv@tempa{##1}{#3}}%
- \skvcsedef{\skv@header#1.@cbk}{\the\skv@toksa}%
}
%% Key names with parenthesized tokens.
@@ -2760,9 +3500,7 @@
% \def\x##1{#1*##1}%
% }
%
-% \skvpntkey[KV]{fam}{evaluate (1) as (2) using (3)}[%
-% \x\y{\numexpr\x*2}
-% ]{%
+% \skvpntkey[KV]{fam}{evaluate (1) as (2) using (3)}[\x\y{\numexpr\x*2}]{%
% \edef\x#2{#3}%
% }
%
@@ -2772,8 +3510,8 @@
%
\skvrobustdef*\skvpntkey{\skv@testoptb\skv@pntkey}
\skvrobustdef*\skv@pntkey#1{%
- \skv@strippointers{#1}\skvcurrentkey
- \skvexpbracenext\skv@extractpntkey\skvcurrentkey\skvcurrentkey
+ \skv@strippointersfromkey{#1}%
+ \skvexpbracenext\skv@extractpntkey@atdefkey\skvcurrentkey\skvcurrentkey
\skvexpanded{\skv@testopt{\skv@pntkey@a{\skvcurrentkey}}{^skv^}}%
}
\skvrobustdef*\skv@pntkey@a#1[#2]#3{%
@@ -2800,15 +3538,17 @@
% When the key's value has doubled hash characters, xkeyval's definition
% of \skv@cmdkey fails:
\skvrobustdef*\skv@cmdkey#1#2[#3]#4{%
- \skv@strippointers{#2}\skvcurrentkey
+ \skv@strippointersfromkey{#2}%
\skvifdefboolTF{skv@st}{\skv@definedefault\skvcurrentkey{#3}}{}%
% This is to allow the key name to be expanded before possibly zapping
% spaces in key name:
\edef\skv@prova{#1\skvcurrentkey}%
\edef\skv@prova{\expandafter\skv@zapornot\expandafter
{\expandafter\skv@zapsw\expandafter}\expandafter{\skv@prova}}%
- \skvcslet{\skv@header\skvcurrentkey.@hp}\skv@prova
- \skvcsedef{\skv@header\skvcurrentkey.@cbk}{\unexpanded{#4}}%
+ \skvcsedef{\skv@header\skvcurrentkey.@cbk}{%
+ \skvcslet{\skv@prova}\noexpand\skvcurrentvalue
+ \unexpanded{#4}%
+ }%
}
% \skvcmdkeys[<pref>]{<fam>}[<mp>]{<keys>}[<defa>]{<callback>}
\skvrobustdef*\skvcmdkeys{%
@@ -2825,6 +3565,107 @@
}%
}
+%% List processor keys.
+%
+% \skvlistkey[<pref>]{<fam>}[<mp>]{<key>}[<defa>]{<callback>}
+%
+\skvrobustdef*\skv@getlistkeyparser#1{%
+ \begingroup
+ \let\skv@prova\undefined
+ \skvxifinTF{\detokenize{\listsep}}{\detokenize{#1}}{%
+ \skvxifinTF{\detokenize{\listparser}}{\detokenize{#1}}{%
+ \skv@err{I find both \noexpand\listsep and \noexpand\listparser in the
+ \MessageBreak callback of key '\skvcurrentfullkey'}\skv@ehd
+ }{%
+ \def\skv@prova{\listsep}%
+ }%
+ }{%
+ \skvxifinTF{\detokenize{\listparser}}{\detokenize{#1}}{%
+ \def\skv@prova{\listparser}%
+ }{}%
+ }%
+ \skvifdefTF\skv@prova{%
+ % Hide the parameter characters in #1 here:
+ \edef\skv@provc{\unexpanded{#1}}%
+ \def\skv@provb##1{%
+ \def\skv@provb####1##1####2####3\skv@listparser@nil{%
+ \skvifblankTF{####2}{%
+ \def\skv@listparser{,}%
+ }{%
+ \edef\skv@listparser{\skvtrimspace{####2}}%
+ }%
+ \edef\skv@callback{\skvtrimspace{####1}\skvtrimspace{####3}}%
+ }%
+ \expandafter\skv@provb\skv@provc\skv@listparser@nil
+ }%
+ \expandafter\skv@provb\expandafter{\skv@prova}%
+ }{%
+ \def\skv@listparser{,}%
+ \edef\skv@callback{\skvtrimspace{#1}}%
+ }%
+ \skvexpanded{\endgroup
+ \skvcmdexit\skv@listparser\skvcmdexit\skv@callback
+ }%
+}
+\skvnewlet\skvstopprocessinglistkey\skvbreakloop
+\skvrobustdef*\skvlistkey{%
+ \def\skv@zapsw{01}%
+ \skv@testoptd\skv@listkey{list}%
+}
+\skvrobustdef*\skvzlistkey{%
+ \def\skv@zapsw{00}%
+ \skv@testoptd\skv@listkey{list}%
+}
+\skvrobustdef*\skv@listkey#1#2[#3]#4{%
+ \skv@strippointersfromkey{#2}%
+ \skvifdefboolTF{skv@st}{\skv@definedefault\skvcurrentkey{#3}}{}%
+ % This is to allow the key name to be expanded before possibly zapping
+ % spaces in key name:
+ \edef\skv@provb{#1\skvcurrentkey}%
+ \edef\skv@provb{\expandafter\skv@zapornot\expandafter
+ {\expandafter\skv@zapsw\expandafter}\expandafter{\skv@provb}}%
+ \skv@getlistkeyparser{#4}%
+ % If there are more parameters in #4 than ####1, the next step
+ % will raise an error:
+ \skvxifinTF{\detokenize{##2}}{\skvoxdetok\skv@callback}{%
+ \skv@err{A listkey can't have more than one
+ \MessageBreak parameter character}\skv@ehd
+ }{%
+ \def\skv@prova{\skvcsdef{\skv@header\skvcurrentkey.@auxcbk}####1}%
+ \expandafter\skv@prova\expandafter{\skv@callback}%
+ }%
+ \let\do\noexpand
+ \skvcsedef{\skv@header\skvcurrentkey.@cbk}{%
+ \skvcslet{\skv@provb}\do\skvcurrentvalue
+ \edef\do\skv@prova{\do\unexpanded{####1}}%
+ \do\skvstripouterbraces{2}\do\skv@prova
+ % 1. \skvprocesslist processes an empty list.
+ % 2. You can call \skvlistcount when processing listkeys, since
+ % \skvprocesslist initializes and increments it.
+ \do\skvprocesslist*{\skv@listparser}\do\skv@prova\do\skv@prova{%
+ \do\csname\skv@header\skvcurrentkey.@auxcbk%
+ \do\expandafter\endcsname\do\expandafter{\do\skv@prova}%
+ }%
+ }%
+ % A listkey must have a 1-parameter argument. We use the following
+ % definition to enforce this requirement:
+ \skvcsdef{\skv@header\skvcurrentkey.@listkey}{}%
+}
+% \skvlistkeys[<pref>]{<fam>}[<mp>]{<keys>}[<defa>]{<callback>}
+\skvrobustdef*\skvlistkeys{%
+ \def\skv@zapsw{01}%
+ \skv@testoptd\skv@listkeys{list}%
+}
+\skvrobustdef*\skvzlistkeys{%
+ \def\skv@zapsw{00}%
+ \skv@testoptd\skv@listkeys{list}%
+}
+\skvrobustdef*\skv@listkeys#1#2[#3]#4{%
+ \skvcommaparse{#2}\skv@tempa{%
+ \skvexpanded{\skv@listkey{#1}{\skv@tempa}}[#3]{#4}%
+ }%
+}
+
%% Choice keys:
%
% The skeyval package allows holder-macro prefixes {<mp>} for choice keys.
@@ -2855,8 +3696,7 @@
\if#1}\fi
\skvstripouterbraces{2}\skv@prova
\edef\skv@altlista{%
- \skvxonce\skv@altlista\ifx\skv@altlista\@empty\else,\fi
- \skvxonce\skv@prova
+ \skvaddlist,\skv@altlista\skvxonce\skv@prova
}%
\edef\reserved@a{%
\skvnoexpandcs{\skvoxdetok\skv@prova @skvch}%
@@ -2868,7 +3708,7 @@
\expandafter\skv@provc\skv@prova.do=.do=\skv@choice@nil
}%
\ifx\skv@altlista\@empty
- \skv@err{No nominations (state pattern) for choice key}\@ehd
+ \skv@err{No nominations (state pattern) for choice key}\skv@ehd
\def\skv@altlistb{}%
\fi
\skvexpanded{\endgroup
@@ -2895,7 +3735,7 @@
\edef\skv@prova{\unexpanded{##2}}%
\ifx\skv@prova\skv@nnil
\skv@err{No state pattern match found for key
- \MessageBreak '\skvcurrentkey'}\@ehd
+ \MessageBreak '\skvcurrentkey'}\skv@ehd
\toks@{}%
\fi
}%
@@ -2911,7 +3751,7 @@
\skvrobustdef*\skv@choicekey@a[#1]#2{%
\skvxifinTF{\skv@hashchar}{\detokenize{#2}}{%
\skv@err{Hash character '\skv@hashchar' not allowed
- \MessageBreak in key name}\@ehd
+ \MessageBreak in key name}\skv@ehd
}{%
\edef\skv@currlist{\unexpanded{#2}}%
\edef\skv@hp{\skvtrimspace{#1}}%
@@ -2927,13 +3767,13 @@
\skvtfor\skv@prova:=#1\do{%
\skvexpbracenext\skvifescapedTF\skv@prova{}{%
\skv@err{Token '\skvoxdetok\skv@prova' of bin of
- \MessageBreak choice key isn't escaped}\@ehd
+ \MessageBreak choice key isn't escaped}\skv@ehd
}%
}%
\fi
\skvifblankTF{#2}{%
\skv@err{No nominations (state pattern) for
- \MessageBreak choice keys '\skv@currlist'}\@ehd
+ \MessageBreak choice keys '\skv@currlist'}\skv@ehd
}{%
\skvifboolTF{skv@st}{%
\skv@preparenominations{00}{#2}%
@@ -2982,15 +3822,17 @@
}
\skvrobustdef*\skv@choicekey@g{%
\skvcommaparse*\skv@currlist\skv@prova{%
- \skvexpbracenext\skv@strippointers\skv@prova\skvcurrentkey
+ \skvexpbracenext\skv@strippointersfromkey\skv@prova
\ifx\skv@default\skv@rej\else
\skvexpanded{%
\noexpand\skv@definedefault
{\skvxonce\skvcurrentkey}{\skvxonce\skv@default}%
}%
\fi
- \skvcsedef{\skv@header\skvcurrentkey.@hp}{\skv@hp\skvcurrentkey}%
- \skvcsedef{\skv@header\skvcurrentkey.@cbk}{\the\skv@toksa}%
+ \skvcsedef{\skv@header\skvcurrentkey.@cbk}{%
+ \skvcslet{\skv@hp\skvcurrentkey}\noexpand\skvcurrentvalue
+ \the\skv@toksa
+ }%
}%
}
@@ -3024,7 +3866,7 @@
}
% \skv@boolkeys{<mp>}{<key>}[<default>]
\skvrobustdef*\skv@boolkey#1#2[#3]{%
- \skv@strippointers{#2}\skvcurrentkey
+ \skv@strippointersfromkey{#2}%
\skvexpanded{%
\ifskv@pl\skv@boolkey@b\else\skv@boolkey@a\fi
{\skvcurrentkey}{#1\skvcurrentkey}%
@@ -3094,7 +3936,7 @@
\skvrobustdef*\skv@boolkeys@b#1#2#3#4#5{\skv@boolkeys@c{#1}{#2}{#3}{#4}{#5}}
\skvrobustdef*\skv@boolkeys@c#1#2#3#4#5{%
\skvcommaparse{#1}\skv@tempa{%
- \skvexpbracenext\skv@strippointers\skv@tempa\skvcurrentkey
+ \skvexpbracenext\skv@strippointersfromkey\skv@tempa
\skvexpanded{%
\skvifstrcmpTF{#5}{^skv^}{%
\skv@boolkey@a{\skvcurrentkey}%
@@ -3145,15 +3987,14 @@
}%
\ifnum\@tempcnta=\tw@\else
\skv@err{Number of bi-keys isn't 2:
- \MessageBreak ||\skv@currlist||}\@ehd
+ \MessageBreak ||\skv@currlist||}\skv@ehd
\fi
\skvexpanded{%
\ifskv@pl\skv@biboolkeys@b\else\skv@biboolkeys@a\fi
{\skv@currlist}%
}{#1}{#3}%
}
-% \skv@bilboolkeys@a{<key1,key2>}{<mp>}{<default>}
-% {<callback1>}{<callback2>}
+% \skv@bilboolkeys@a{<key1,key2>}{<mp>}{<default>}{<callback1>}{<callback2>}
\skvrobustdef*\skv@biboolkeys@a#1#2#3#4#5{%
\skv@biboolkeys@c{#1}{#2}{#3}{#4}{#5}{^skv^}%
}
@@ -3172,7 +4013,7 @@
\edef\skv@tempd{\unexpanded{#5}}%
\edef\skv@tempe{\unexpanded{#6}}%
\toks@{}\def\skv@provd{}%
- \let\\\noexpand
+ \let\nx\noexpand
\def\@do##1##2{%
\skvifcsname\skv@header##1.@##2\then
\edef\skv@provd{%
@@ -3186,12 +4027,12 @@
\def\skv@provc##1##2##3##4{%
\skvsettogtrue{\skv@header bicallerid/##3}%
\skvxonce\@elt
- \\\skvifxTF\\\skvcurrentvalue\\\skv@truetoks{%
- \\\skviftogTF{\skv@header bicallerid/##4}{}{%
+ \nx\skvifxTF\nx\skvcurrentvalue\nx\skv@truetoks{%
+ \nx\skviftogTF{\skv@header bicallerid/##4}{}{%
\skvsetkeys[##1]{##2}{##4=false}%
}%
}{%
- \\\skviftogTF{\skv@header bicallerid/##4}{}{%
+ \nx\skviftogTF{\skv@header bicallerid/##4}{}{%
\skvsetkeys[##1]{##2}{##4=true}%
}%
}%
@@ -3218,14 +4059,16 @@
}%
}%
\def\skv@prova##1,##2\skv@nil{%
- \skv@strippointers{##1}\skv@tempa
- \skv@strippointers{##2}\skv@tempb
+ \skv@strippointersfromkey{##1}%
+ \let\skv@tempa\skvcurrentkey
+ \skv@strippointersfromkey{##2}%
+ \let\skv@tempb\skvcurrentkey
\skvexpanded{%
- \let\\\@elt\\\skv@tempc
- \\\skv@provb{\skvcurrentprefix}{\skvcurrentfamily}%
+ \let\nx\@elt\nx\skv@tempc
+ \nx\skv@provb{\skvcurrentprefix}{\skvcurrentfamily}%
{\skv@tempa}{\skv@tempb}%
- \let\\\@elt\\\skv@tempd
- \\\skv@provb{\skvcurrentprefix}{\skvcurrentfamily}%
+ \let\nx\@elt\nx\skv@tempd
+ \nx\skv@provb{\skvcurrentprefix}{\skvcurrentfamily}%
{\skv@tempb}{\skv@tempa}%
}%
}%
@@ -3260,6 +4103,10 @@
\def\skv@zapsw{00}%
\skv@t@stopta{\skv@testoptd\skv@boolkeys{}}%
}
+% \skvbitogkeys[<pref>]{<fam>}[<mp>]{<key1,key2>}[<defa>]
+% {<callback.for.key1>}{<callback.for.key2>}
+% \skvbitogkeys+[<pref>]{<fam>}[<mp>]{<key1,key2>}[<defa>]
+% {<callback.for.key1>}{<callback.for.key2>}{<fallback>}
\skvrobustdef*\skvbitogkeys{%
\def\skv@typetogkey{00}%
\def\skv@zapsw{01}%
@@ -3270,126 +4117,211 @@
\def\skv@zapsw{00}%
\skv@t@stopta{\skv@testoptd\skv@biboolkeys{}}%
}
+\skvrobustdef*\skvSignalkeyPresetException#1{%
+ \edef\skv@signalpreseterr{\unexpanded{#1}}%
+}
+\skvSignalkeyPresetException{%
+ \@latex@error{%
+ Key '\skvcurrentfullkey'
+ \MessageBreak is a signal key. It shouldn't have
+ \MessageBreak been preset. Presetting signal keys
+ \MessageBreak does lead to cyclic key setting
+ }\skv@ehd
+}
-% Style keys
+% Declare prefix and family and then define/set keys on them (without
+% the need to give prefix and family). This can be handy if all the keys
+% in a project have the same prefix and family.
%
-% \skvappendstyles[<pref>]{<fam>}{<keys>}{<styles>}[<defa>]{<callback>}
-% \skvprependstyles[<pref>]{<fam>}{<keys>}{<styles>}[<defa>]{<callback>}
+% Example:
%
-% 1. Style keys will be created if they didn't exist. If they existed,
-% (a) their default values will be overwritten if the option [<defa>]
-% appears in the above syntax; (b) their callbacks will be updated with
-% <callback> and <styles>.
+% \skvsetprefix{KV}
+% \skvsetfamily{fam}
+% \skvdefineordkey{key1}[default]{\def\x##1{##1*#1}}
+% \skvprocesskeys{key1=value1}
+%
+\skvrobustdef*\skvsetprefix{\def\skv@currpref}
+\skvrobustdef*\skvsetfamily{\def\skv@currfam}
+\skvrobustdef*\skv@defineonmeta#1{%
+ \ifdefined\skv@currpref\else
+ \let\skv@currpref\skvdefaultprefix
+ \fi
+ \skvexpanded{\noexpand#1[\skv@currpref]{\skv@currfam}}%
+}
+\skvrobustdef*\skvdefineordkey{\skv@defineonmeta\skvordkey}
+\skvrobustdef*\skvdefineordkeys{\skv@defineonmeta\skvordkeys}
+\skvrobustdef*\skvdefinecmdkey{\skv@defineonmeta\skvcmdkey}
+\skvrobustdef*\skvdefinecmdkeys{\skv@defineonmeta\skvcmdkeys}
+\skvrobustdef*\skvdefineboolkey{\skv@defineonmeta\skvboolkey}
+\skvrobustdef*\skvdefineboolkeys{\skv@defineonmeta\skvboolkeys}
+\skvrobustdef*\skvdefinebiboolkeys{\skv@defineonmeta\skvbiboolkeys}
+\skvrobustdef*\skvdefinetogkey{\skv@defineonmeta\skvtogkey}
+\skvrobustdef*\skvdefinetogkeys{\skv@defineonmeta\skvtogkeys}
+\skvrobustdef*\skvdefinechoicekey{\skv@defineonmeta\skvchoicekey}
+\skvrobustdef*\skvdefinechoicekeys{\skv@defineonmeta\skvchoicekeys}
+\skvrobustdef*\skvprocesskeys{\skv@defineonmeta\skvsetkeys}
+
+% Signal-slot keys:
+%
+% \skvappendslots[<pref>]{<fam>}{<signal.keys>}{<slots>}
+% [<signal default>]{<signal callback>}
+% \skvprependslots[<pref>]{<fam>}{<signal.keys>}{<slots>}
+% [<signal default>]{<signal callback>}
+%
+% 1. <slots> must pre-exist. If slot key is undefined, then the signal-slot
+% system isn't useful here since the slot will serve no purpose.
%
% 2. If desired, use pointers/handlers .expanded, .expand once, .expand twice
-% on values of styles.
+% on values of <slots>.
+%
+% 3. Here, it helps to consider <keys> as parents (or signals or
+% subjects) and <slots> as children (or slots or observers).
+%
+% 4. <signal.keys> can't be preset, to avoid cyclic setting of keys.
+% Consider the following, for a signal key in the preset list:
+%
+% set any key on a path -> preset 'signal'
+% -> set 'slot' -> preset 'signal'.
+%
+% In the attempt to set a slot key, the preset list (that includes
+% the signal key) will be instantiated.
%
% Example:
%
% \skvordkeys[KV]{fam}{keya,keyb}{\def\x##1{#1*##1}}
-% \skvappendstyles[KV]{fam}{keyd,keye}{keya=.expanded{\vala},keyb=valb}
+% \skvappendslots[KV]{fam}{keyd,keye}{keya=.expanded{\vala},keyb=valb}
% [def-d&e]{\def\y##1{#1*##1}}
%
-\skvrobustdef*\skvappendstyles{%
+\skvrobustdef*\skvappendslots{%
\def\skv@type{app}%
- \def\skvexpanderpointer{}%
- \skv@testoptb\skv@appendstyles
+ \let\skvexpanderpointer\@iden
+ \skv@testoptb\skv@appendslots
}
-\skvnewlet\skvstylekeys\skvappendstyles
-\skvrobustdef*\skvprependstyles{%
+\skvrobustdef*\skvprependslots{%
\def\skv@type{prep}%
- \def\skvexpanderpointer{}%
- \skv@testoptb\skv@appendstyles
+ \let\skvexpanderpointer\@iden
+ \skv@testoptb\skv@appendslots
}
-\skvrobustdef*\skvappendstylesexpanded{%
+\skvrobustdef*\skvappendslotsexpanded{%
\def\skv@type{app}%
\def\skvexpanderpointer{.expanded}%
- \skv@testoptb\skv@appendstyles
+ \skv@testoptb\skv@appendslots
}
-\skvnewlet\skvstylekeysexpanded\skvappendstylesexpanded
-\skvrobustdef*\skvprependstylesexpanded{%
+\skvrobustdef*\skvprependslotsexpanded{%
\def\skv@type{prep}%
\def\skvexpanderpointer{.expanded}%
- \skv@testoptb\skv@appendstyles
+ \skv@testoptb\skv@appendslots
}
-\skvrobustdef*\skv@appendstyles#1#2{%
- \skv@testopt{\skv@appendstyles@a{#1}{#2}}{^skv^}%
+\skvrobustdef*\skv@appendslots#1#2{%
+ \skv@testopt{\skv@appendslots@a{#1}{#2}}{^skv^}%
}
-% #2: styles, #3: default, #4: callback
-\skvrobustdef*\skv@appendstyles@a#1#2[#3]#4{%
+% #1=signal keys, #2=slot keys, #3=signal default, #4=signal callback
+\skvrobustdef*\skv@appendslots@a#1#2[#3]#4{%
\skvcommaparse{#1}\skv@prova{%
- \skvexpbracenext\skv@strippointers\skv@prova\skvcurrentkey
+ \skvexpbracenext\skv@strippointersfromkey\skv@prova
\skvexpanded{%
\skvifstrcmpTF{#3}{^skv^}{}{%
+ % If the signal aready exists, the default value will be
+ % overridden:
\skv@definedefault{\skvcurrentkey}{\unexpanded{#3}}%
}%
- \skv@appendstyles@b{\skvcurrentkey}\unexpanded{{#2}{#4}}%
+ \skv@appendslots@b{\skvcurrentkey}\unexpanded{{#2}{#4}}%
}%
}%
}
-% \skv@appendstyles@b{<parent.key>}{<styles>}{<parent.key.callback>}
-\skvrobustdef*\skv@appendstyles@b#1#2#3{%
- \def\skv@stylelist{}%
+% \skv@appendslots@b{<signal>}{<slots>}{<signal.callback>}
+\skvrobustdef*\skv@appendslots@b#1#2#3{%
+ \def\skv@slotlist{}%
\skvkvparse{#2}\skv@prova{%
- \ksv@kvosplit\skv@prova{%
+ \skv@okvsplit\skv@prova{%
\skvxifstrcmpTF{#1}{##1}{%
- \skv@err{Linking key '##1' to itself}\@ehd
+ \skv@err{Linking key '##1' to itself}\skv@ehd
}{%
+ % If slot key is undefined, then the signal-slot system isn't
+ % useful, since the slot won't be able to do anything with the
+ % emitted signal.
\skvifcsdefTF{\skv@header##1.@cbk}{}{%
- \skv@err{Style key '##1' is undefined}\@ehd
+ \skv@err{Slot key '\skvcurrentpath/##1'
+ \MessageBreak is undefined}\skv@ehd
}%
}%
- \edef\skv@stylelist{%
- \skvaddlist,\skv@stylelist\unexpanded{##1}=%
- \skvexpandonce\skvexpanderpointer{\unexpanded{##2}}%
+ \edef\skv@slotlist{%
+ \skvaddlist,\skv@slotlist\unexpanded{##1}=%
+ \skvexpanderpointer{\unexpanded{##2}}%
}%
}%
}%
+ \edef\skv@elt{%
+ % Signal keys shouldn't be preset, to avoid cyclic setting of keys.
+ % See note above.
+ \noexpand\skvifdefboolTF{skv@inprepo}{%
+ \noexpand\skv@signalpreseterr
+ }{%
+ \noexpand\skvsetkeys[\skvcurrentprefix]%
+ {\skvcurrentfamily}{\skvexpandonce\skv@slotlist}%
+ }%
+ }%
+ % The signal key might already exists, especially when calling
+ % \skvaddslots:
\edef\elt{%
\skvifcsdefTF{\skv@header#1.@cbk}
- {\skvxpandcsonce{\skv@header#1.@cbk}}{}%
- }%
- \edef\skv@elt{%
- \noexpand\skvexpanded{\noexpand\skvsetkeys[\skvcurrentprefix]%
- {\skvcurrentfamily}{\skvexpandonce\skv@stylelist}}%
+ {\skvexpandcsonce{\skv@header#1.@cbk}}{}%
}%
\skvcsedef{\skv@header#1.@cbk}{%
\skvxifstrcmpTF{\skv@type}{prep}{%
- \skvexpandonce\skv@elt\unexpanded{#3}\skvexpandonce\elt
+ \skvexpandonce\skv@elt\skvtrimspace{#3}\skvexpandonce\elt
}{%
- \skvexpandonce\elt\unexpanded{#3}\skvexpandonce\skv@elt
+ \skvexpandonce\elt\skvtrimspace{#3}\skvexpandonce\skv@elt
}%
}%
}
%
-% \skvaddstyles[<pref>]{<fam>}{<keys>}{<prepend>}{<append>}[<defa>]{<callback>}
+% \skvaddslots[<pref>]{<fam>}{<signals>}{<prepended.slots>}
+% {<appended.slots>}[<signal.default>]{<signal.callback>}
%
-% Example:
+% Slot keys are observer keys that receive signals from signal
+% (ie, subject) keys.
+%
+% Examples:
% \skvordkeys[KV]{fam}{keya1,keyb1,keya2,keyb2}{\def\x##1{#1*##1}}
-% \skvaddstyles[KV]{fam}{keyd,keye}{keya1=vala,keyb1=valb}
+% \skvaddslots[KV]{fam}{keyd,keye}{keya1=vala,keyb1=valb}
% {keya2=vala,keyb2=.expanded{\valb}}[def-d&e]{\def\y##1{#1*##1}}
%
-\skvrobustdef*\skvaddstyles{%
- \def\skvexpanderpointer{}%
- \skv@testoptb\skv@addstyles
+% \skvordkeys{graph}{avertices,bvertices}[6]{\def\x##1{#1+##1}}
+% \skvaddslots{graph}{vertices}{avertices=4}{bvertices=8}[6]
+% {\def\y##1{#1*##1}}
+% \skvsetkeys{graph}{vertices=6}
+%
+\skvrobustdef*\skvaddslots{%
+ \let\skvexpanderpointer\@iden
+ \skv@testoptb\skv@addslots
}
-\skvrobustdef*\skv@addstyles#1#2#3{%
- \skv@testopt{\skv@addstyles@a{#1}{#2}{#3}}{^skv^}%
+\skvrobustdef*\skv@addslots#1#2#3{%
+ \skv@testopt{\skv@addslots@a{#1}{#2}{#3}}{^skv^}%
}
-% #2: prepended styles
-% #3: appended styles
-% #4: default
-% #5: callback
-\skvrobustdef*\skv@addstyles@a#1#2#3[#4]#5{%
+% \skv@addslots@a{<signals>}{<prepended slots>}{<appended slots>}
+% [<signal default>]{<signal callback>}
+\skvrobustdef*\skv@addslots@a#1#2#3[#4]#5{%
\skvexpanded{%
- \skvprependstyles[\skvcurrentprefix]{\skvcurrentfamily}%
+ \skvprependslots[\skvcurrentprefix]{\skvcurrentfamily}%
\unexpanded{{#1}{#2}[#4]{#5}}%
- \skvappendstyles[\skvcurrentprefix]{\skvcurrentfamily}%
+ \skvappendslots[\skvcurrentprefix]{\skvcurrentfamily}%
\unexpanded{{#1}{#3}[#4]{#5}}%
}%
}
-
-%% Checking the admissible values of keys:
+\skvnewcastcommands{%
+ \skvslotkeys=\skvappendslots,\skvstylekeys=\skvappendslots,
+ \skvprependstyles=\skvprependslots,
+ \skvappendstylesexpanded=\skvappendslotsexpanded,
+ \skvprependstylesexpanded=\skvprependslotsexpanded,
+ \skvaddstyles=\skvaddslots,
+ \skvobserverkeys=\skvappendslots,
+ \skvprependobservers=\skvprependslots,
+ \skvappendobserversexpanded=\skvappendslotsexpanded,
+ \skvprependobserversexpanded=\skvprependslotsexpanded,
+ \skvaddobservers=\skvaddslots
+}
+% Checking the admissible values of keys:
%
\skvrobustdef*\skvcheckchoice{\skv@testopta{\skv@testopt\skv@checkchoice{}}}
\skvrobustdef*\skv@checkchoice[#1]#2#3{%
@@ -3434,7 +4366,7 @@
\ifskv@pl
\skvappendtomacro\skv@tempa{\@secondoftwo}%
\else
- \skv@err{Value '\detokenize{#2}' is not allowed}\@ehd
+ \skv@err{Value '\detokenize{#2}' is not allowed}\skv@ehd
\skvappendtomacro\skv@tempa{\@gobble}%
\fi
}%
@@ -3453,7 +4385,7 @@
\ifskv@pl
\edef\skv@tempb{\skv@prova\@secondoftwo}%
\else
- \skv@err{Value '\detokenize{#3}' is not allowed}\@ehd
+ \skv@err{Value '\detokenize{#3}' is not allowed}\skv@ehd
\edef\skv@tempb{\skv@prova\@gobble}%
\fi
\else
@@ -3476,12 +4408,14 @@
\skvrobustdef*\skv@checkchoice@e#1\skv@nil,{\@firstofone}
% \skvifkeydefTF[<prefs>]{<fams>}{key}{<true>}{<false>}
+%
% 1. The search will stop as soon as the key is found in one combination
% of prefixes/families.
% 2. The prefix and header created here may be needed in #5 and #6. Hence
% we put entry prefix and header on stack before commencing the search.
-\skvrobustdef*\skvifkeydefTF{\skv@testopt{\skv@ifkeyundef0}\skv@defaultpref}
-\skvrobustdef*\skvifkeydefFT{\skv@testopt{\skv@ifkeyundef1}\skv@defaultpref}
+%
+\skvrobustdef*\skvifkeydefTF{\skv@testopt{\skv@ifkeyundef0}\skvdefaultprefix}
+\skvrobustdef*\skvifkeydefFT{\skv@testopt{\skv@ifkeyundef1}\skvdefaultprefix}
\skvrobustdef*\skv@ifkeyundef#1[#2]#3#4#5#6{%
\skvpushstate\skv@keystate\skv@keydepth
\edef\skv@prefs{#2}%
@@ -3494,6 +4428,7 @@
\skvcommaparse*\skv@prefs\skv@prova{%
\skv@makeprefix\skv@prova
\skv@ifk@yundef
+ % Break outer loop as needed:
\ifskv@kf\skvbreakloop\fi
}%
\skvexpanded{%
@@ -3510,8 +4445,7 @@
\noexpand\@firstoftwo
\fi
}%
- }%
- {#5}{#6}%
+ }{#5}{#6}%
\skvpopstate\skv@keystate\skv@keydepth
}
\skvrobustdef*\skv@ifk@yundef{%
@@ -3525,13 +4459,27 @@
% \skvifkeyinfamiliesTF[<prefs>]{<fams>}{key}{<true>}{<false>}
%
% The search will be done on all combinations of prefixes/families. The
-% callback <true> or <false> will be executed for all the combinations.
+% callback <true> or <false> will be executed for ALL the combinations.
%
\skvrobustdef*\skvifkeyinfamiliesTF{%
- \skv@testopt{\skv@ifkeyinfamilies0}\skv@defaultpref
+ \skv@testopt{\skv@ifkeyinfamilies0}\skvdefaultprefix
+}
+% \skvdoonallpathsfound[<prefs>]{<fams>}{key}{<true>}
+\skvrobustdef*\skvdoonallpathsfound{%
+ \skv@testopt\skv@doonallpathsfound\skvdefaultprefix
+}
+\skvrobustdef*\skv@doonallpathsfound[#1]#2#3#4{%
+ \skv@ifkeyinfamilies0[#1]{#2}{#3}{#4}{}%
+}
+% \skvdoonallpathsnotfound[<prefs>]{<fams>}{key}{<false>}
+\skvrobustdef*\skvdoonallpathsnotfound{%
+ \skv@testopt\skv@doonallpathsnotfound\skvdefaultprefix
+}
+\skvrobustdef*\skv@doonallpathsnotfound[#1]#2#3#4{%
+ \skv@ifkeyinfamilies0[#1]{#2}{#3}{}{#4}%
}
\skvrobustdef*\skvifkeyinfamiliesFT{%
- \skv@testopt{\skv@ifkeyinfamilies1}\skv@defaultpref
+ \skv@testopt{\skv@ifkeyinfamilies1}\skvdefaultprefix
}
\skvrobustdef*\skv@ifkeyinfamilies#1[#2]#3#4#5#6{%
\skvpushstate\skv@keystate\skv@keydepth
@@ -3572,6 +4520,7 @@
\skvnewdef*\skvifkeyincurrentfamilyTF#1{%
\skvifcsdefTF{\skvcurrentpath/\skvtrimspace{#1}.@cbk}%
}
+\skvnewlet\skvifkeyoncurrentpathTF\skvifkeyincurrentfamilyTF
% \skvifonekeyinfamilyTF{<prefix>/<family>}{<keys>}
% Given a list of keys, test if at least one of them is defined.
% Example: \edef\x{\skvifonekeyinfamilyTF{KV/fam}{keya,keyb,keyc}{T}{F}}.
@@ -3592,10 +4541,49 @@
{#1}%
}
+% \skvgetdefinedkeys[<pref>]{<fams>}{<keys>}
+%
+% 1. Get keys defined on the given paths.
+% 2. Remove any redundant star (*) and plus (+) suffix on
+% \skvgetdefinedkeys.
+\skvrobustdef*\skvgetdefinedkeys{%
+ \skv@testopta{\skv@testopt\skv@getdefinedkeys\skvdefaultprefix}%
+}
+\skvrobustdef*\skv@getdefinedkeys[#1]#2#3{%
+ \begingroup
+ \skv@makeprefix{#1}%
+ \def\skv@tempa{}%
+ \skvcommaparse{#2}\skvcurrentfamily{%
+ \skv@makeheader\skvcurrentfamily
+ % Prepare to take defined keys outside the group:
+ \skvxifinTF{\skvoxdetok\skv@header}{\skvoxdetok\skv@tempa}{}{%
+ \edef\skv@tempa{%
+ \skvexpandonce\skv@tempa
+ \noexpand\skvcsexit{\skvcurrentpath.@definedkeys}%
+ }%
+ }%
+ \skvcommaparse{#3}\skvcurrentkey{%
+ \skvifcsdefFT{\skv@header\skvcurrentkey.@cbk}{}{%
+ \skvletcs\skv@prova{\skvcurrentpath.@definedkeys}%
+ \skvifdefTF\skv@prova{%
+ \skvxifinTF{,\skvoxdetok\skvcurrentkey,}{,\skvoxdetok\skv@prova,}{}{%
+ \skvcsedef{\skvcurrentpath.@definedkeys}{\skv@prova,\skvcurrentkey}%
+ }%
+ }{%
+ \skvcsedef{\skvcurrentpath.@definedkeys}{\skvcurrentkey}%
+ }%
+ }%
+ }%
+ }%
+ \skvexpanded{\endgroup\skv@tempa}%
+}
+
% \skvvalueof{<pref>}{<family>}{<key>}
\skvnewdef*\skvvalueof#1#2#3{\skvcsuse{#1/#2/#3.@value}}
+% \skvvalueofkey{<pref>/<family>/<key>}
+\skvnewdef*\skvvalueofkey#1{\skvcsuse{#1.@value}}
-% When <pref> isn't given, the following will use 'KV' for <pref>.
+% When <pref> isn't given, the following will use 'default KV' for <pref>.
% \skvprintvalue[<pref>]{<family>}{<key>}
\skvrobustdef*\skvprintvalue{\skv@testoptb\skv@printvalue}
\skvrobustdef*\skv@printvalue#1{\skvcsuse{\skv@header#1.@value}}
@@ -3612,30 +4600,43 @@
% \skvconveyinikv[<pref>]{<family>}<cmd>
\skvrobustdef*\skvconveyinikv{\skv@testoptb\skv@conveyinikv}
-\skvrobustdef*\skv@conveyinikv#1{\skvletcs#1{\skv@header.@inikv}}
+\skvrobustdef*\skv@conveyinikv#1{\skvletcs#1{\skvcurrentpath.@inikv}}
% \skvkeyslet[<pref>]{<family>}{<list>}
-% <list> -> <new keyname>=<old keyname>
+%
+% <list> -> {<newkey1>,<newkey2>,...,<newkey-n>}={<oldkey>}
+%
+% Note: <oldkey> must be only one key, to avoid letting one newkey
+% to two oldkeys.
+%
\skvrobustdef*\skvkeyslet{\skv@testoptb\skv@keyslet}
-\skvnewlet\skvkeyinheritance\skvkeyslet
-\skvnewlet\skvkeylet\skvkeyslet
+\skvnewlet\skvkeyinherit\skvkeyslet
\skvrobustdef*\skv@keyslet#1{%
- \skvletcs\skv@inikv{\skv@header.@inikv}%
+ \skvletcs\skv@inikv{\skvcurrentpath.@inikv}%
\skvifdefFT\skv@inikv{}{%
- \expandafter\skv@getkeynames\expandafter{\skv@inikv}\skv@inikeys
+ \skvexpbracenext\skv@getnamesofkeys\skv@inikv\skv@inikeys
+ }%
+ \def\skv@keyslet@do@a##1=##2=##3\skv@nil{%
+ \skvifinTF{,}{##2}{%
+ \skv@err{There more than one old key:\MessageBreak '##2'}\skv@ehd
+ }{%
+ \skvcommaparse{##1}\skv@prova{%
+ \skvexpbracenext\skv@keyslet@do@b\skv@prova{##2}%
+ }%
+ }%
}%
- \def\skv@k@yslet##1=##2=##3\skv@nil{%
- \skvifcsdefFT{\skv@header##2.@cbk}{%
- \skv@err{Key '\skvcurrentpath/##2' is undefined}\@ehd
+ \def\skv@keyslet@do@b##1##2{%
+ \skvifnamedefFT{\skv@header##2.@cbk}{%
+ \skv@err{Key '\skvcurrentpath/##2'\MessageBreak is undefined}\skv@ehd
}{%
- \skvifcsdefTF{\skv@header##1.@cbk}{%
- \skv@err{Key '\skvcurrentpath/##1' is already defined}\@ehd
+ \skvifnamedefTF{\skv@header##1.@cbk}{%
+ \skv@err{Key '\skvcurrentpath/##1' is already defined}\skv@ehd
}{}%
}%
- \skvcommaloop{cbk,ndv,fbv}\skv@prova{%
+ \skvcommaloop{cbk,ndv,gnv,fbv,gfv}\skv@prova{%
\skvcsletcs{\skv@header##1.@\skv@prova}{\skv@header##2.@\skv@prova}%
}%
- \skvifcsdefTF{\skv@header##2.@defa}{%
+ \skvifnamedefTF{\skv@header##2.@defa}{%
\edef\skvcurrentkey{##2}%
\skv@getdefault\skvcurrentprefix\skvcurrentfamily\skvcurrentkey
\skvcurrentvalue
@@ -3648,27 +4649,28 @@
}%
\skvifdefFT\skv@inikv{}{%
\skvxifinFT{,\detokenize{##2},}{,\skvoxdetok\skv@inikeys,}{}{%
- \skvcsedef{\skv@header.@inikv}{%
- \expandafter\skvaddlist\expandafter
- ,\csname\skv@header.@inikv\endcsname
+ \skvcsedef{\skvcurrentpath.@inikv}{%
+ \skvcsaddlist,{\skvcurrentpath.@inikv}%
##1\ifskv@swa=\skvexpandonce\skvcurrentvalue\fi
}%
}%
}%
\skvcommaloop{ignoredkeys,needini}\skv@prova{%
- \skvletcs\skv@tempa{\skv@header.@\skv@prova}%
+ \skvletcs\skv@tempa{\skvcurrentpath.@\skv@prova}%
\skvifdefFT\skv@tempa{}{%
\skvxifinFT{,\detokenize{##2},}{,\skvoxdetok\skv@tempa,}{}{%
- \skvcsedef{\skv@header.@\skv@prova}{\skvaddlist,\skv@tempa##1}%
+ \skvcsedef{\skvcurrentpath.@\skv@prova}{%
+ \skvaddlist,\skv@tempa##1%
+ }%
}%
}%
}%
}%
\skvkvparse{#1}\skv@prova{%
- \expandafter\skv@k@yslet\skv@prova==\skv@nil
+ \expandafter\skv@keyslet@do@a\skv@prova==\skv@nil
}%
\let\do\skvundef
- \do\skv@k@yslet\do\skv@inikv\do\skv@inikeys
+ \do\skv@keyslet@do\do\skv@inikv\do\skv@inikeys
}
\skvrobustdef*\skv@disabledkeywarning#1{%
@@ -3685,42 +4687,53 @@
\MessageBreak earlier \ifskv@latex in \noexpand\documentclass or
\string\usepackage\fi}%
}
-\skvrobustdef*\skvdisabledkeysmessagetype#1{%
+% A key may be disabled long before \skvmessagetypefordisabledkey
+% is called.
+\skvrobustdef*\skvmessagetypefordisabledkey#1{%
\edef\skv@prova{\skvtrimspace{#1}}%
\def\skv@provb##1{%
\def\skv@provb####1##1####2####3\@nil{%
\ifcase####2\relax
- \let\skv@disabledmsg\skv@disabledkeywarning
+ \let\skv@disabledkeymsg\skv@disabledkeywarning
\or
- \let\skv@disabledmsg\skv@disabledkeywarning
+ \let\skv@disabledkeymsg\skv@disabledkeywarning
\or
- \let\skv@disabledmsg\skv@disabledkeyerror
+ \let\skv@disabledkeymsg\skv@disabledkeyerror
\or
- \let\skv@disabledmsg\@gobble
+ \let\skv@disabledkeymsg\@gobble
\else
- \skv@err{Invalid message type '#1' for disabled keys}\@ehd
+ \skv@err{Invalid message type '#1' for disabled keys}\skv@ehd
\fi
}%
\skv@provb warn{0}warning{1}error{2}nothing{3}##1{10}\@nil
}%
\expandafter\skv@provb\expandafter{\skv@prova}%
}
+\skvnewlet\skvdisabledkeysmessagetype\skvmessagetypefordisabledkey
\skvdisabledkeysmessagetype{warn}
-\skvrobustdef*\skvdisablekeys{\skv@testoptb\skv@disablekeys}
+\skvrobustdef*\skvdisablekeys{%
+ \def\skv@tempa{\skv@ordkey@a{e}}%
+ \skv@testoptb\skv@disablekeys
+}
+\skvrobustdef*\skvgdisablekeys{%
+ \def\skv@tempa{\skv@ordkey@a{x}}%
+ \skv@testoptb\skv@disablekeys
+}
\skvrobustdef*\skv@disablekeys#1{%
- \skvcommaparse{#1}\skv@tempa{%
- \skvifcsdefTF{\skv@header\skv@tempa.@cbk}{}{%
- \skv@err{Key '\skv@tempa' is undefined:
- \MessageBreak couldn't be disabled}\@ehd
- }%
- \skvifcsdefTF{\skv@header\skv@tempa.@defa}{%
- \edef\skv@tempb{\noexpand\skv@ordkey{\skv@tempa}[]}%
+ \skvcommaparse{#1}\skv@prova{%
+ \skvifcsdefTF{\skv@header\skv@prova.@cbk}{%
+ \skvifcsdefTF{\skv@header\skv@prova.@defa}{%
+ \edef\skv@provb{\noexpand\skv@tempa{\skv@prova}[]}%
+ }{%
+ \edef\skv@provb{\noexpand\skv@tempa{\skv@prova}[^skv^]}%
+ }%
+ \expandafter\skv@provb\expandafter{\expandafter
+ \skv@disabledkeymsg\expandafter{\skv@prova}}%
}{%
- \edef\skv@tempb{\noexpand\skv@ordkey{\skv@tempa}}%
+ \skv@err{Key '\skv@prova' is undefined:
+ \MessageBreak couldn't be disabled}\skv@ehd
}%
- \expandafter\skv@tempb\expandafter{\expandafter\skv@disabledmsg
- \expandafter{\skv@tempa}}%
}%
}
@@ -3730,13 +4743,13 @@
%
% \skvpresetkeys[<pref>]{<fam>}{<keys>}
% \skvgpresetkeys[<pref>]{<fam>}{<keys>}
-\skvrobustdef*\skvpresetkeys{\skv@testopt\skv@presetkeys\skv@defaultpref}
+\skvrobustdef*\skvpresetkeys{\skv@testopt\skv@presetkeys\skvdefaultprefix}
\skvrobustdef*\skv@presetkeys[#1]#2#3{\skvpreposetkeys[#1]{#2}{#3}{}}
-\skvrobustdef*\skvgpresetkeys{\skv@testopt\skv@gpresetkeys\skv@defaultpref}
+\skvrobustdef*\skvgpresetkeys{\skv@testopt\skv@gpresetkeys\skvdefaultprefix}
\skvrobustdef*\skv@gpresetkeys[#1]#2#3{\skvgpreposetkeys[#1]{#2}{#3}{}}
-\skvrobustdef*\skvpostsetkeys{\skv@testopt\skv@postsetkeys\skv@defaultpref}
+\skvrobustdef*\skvpostsetkeys{\skv@testopt\skv@postsetkeys\skvdefaultprefix}
\skvrobustdef*\skv@postsetkeys[#1]#2#3{\skvpreposetkeys[#1]{#2}{}{#3}}
-\skvrobustdef*\skvgpostsetkeys{\skv@testopt\skv@gpostsetkeys\skv@defaultpref}
+\skvrobustdef*\skvgpostsetkeys{\skv@testopt\skv@gpostsetkeys\skvdefaultprefix}
\skvrobustdef*\skv@gpostsetkeys[#1]#2#3{\skvgpreposetkeys[#1]{#2}{}{#3}}
\skvrobustdef*\skvpreposetkeys{\skv@clfalse\skv@testoptb\skv@preposetkeys}
\skvrobustdef*\skvgpreposetkeys{\skv@cltrue\skv@testoptb\skv@preposetkeys}
@@ -3745,10 +4758,10 @@
\skvifblankTF{#2}{}{\skv@pr@posetkeys{#2}{postset}}%
}
\skvrobustdef*\skv@pr@posetkeys#1#2{%
- \skvifcsdefFT{\skv@header.@#2}{%
+ \skvifcsdefFT{\skvcurrentpath.@#2}{%
\skvnormalize{csv}{,}{#1}\skv@tempa
\ifskv@cl\expandafter\global\fi
- \expandafter\def\csname\skv@header.@#2\expandafter
+ \expandafter\def\csname\skvcurrentpath.@#2\expandafter
\endcsname\expandafter{\skv@tempa}%
}{%
% Don't change \skv@filtermergelist to \skvfiltermergelist:
@@ -3765,12 +4778,11 @@
\skv@cltrue\skv@testoptb\skv@removepresetkeys
}
\skvrobustdef*\skv@removepresetkeys#1{%
- \skvifcsdefTF{\skv@header.@preset}{%
+ \skvifcsdefTF{\skvcurrentpath.@preset}{%
\expandafter\skv@filterremoveelements\csname\skv@header
.@preset\endcsname{#1}\skv@getkeyname
}{%
- \skv@err{No preset keys defined for
- '\skvcurrentprefix/\skvcurrentfamily'}\@ehd
+ \skv@err{No preset keys defined for '\skvcurrentpath'}\skv@ehd
}%
}
% \skvundefpresetkeys[<pref>]{<fam>}
@@ -3781,12 +4793,11 @@
\skv@cltrue\skv@testoptb\skv@undefpresetkeys
}
\skvrobustdef*\skv@undefpresetkeys{%
- \skvifcsdefFT{\skv@header.@preset}{%
- \skv@err{No preset keys defined for
- '\skvcurrentprefix/\skvcurrentfamily'}\@ehd
+ \skvifcsdefFT{\skvcurrentpath.@preset}{%
+ \skv@err{No preset keys defined for '\skvcurrentpath'}\skv@ehd
}{%
\ifskv@cl\expandafter\global\fi
- \skvcsundef{\skv@header.@preset}%
+ \skvcsundef{\skvcurrentpath.@preset}%
}%
}
@@ -3799,12 +4810,11 @@
\skv@cltrue\skv@testoptb\skv@removepostsetkeys
}
\skvrobustdef*\skv@removepostsetkeys#1{%
- \skvifcsdefTF{\skv@header.@postset}{%
+ \skvifcsdefTF{\skvcurrentpath.@postset}{%
\expandafter\skv@filterremoveelements\csname\skv@header
.@postset\endcsname{#1}\skv@getkeyname
}{%
- \skv@err{No postset keys defined for
- '\skvcurrentprefix/\skvcurrentfamily'}\@ehd
+ \skv@err{No postset keys defined for '\skvcurrentpath'}\skv@ehd
}%
}
% \skvundefpostsetkeys[<pref>]{<fam>}
@@ -3815,12 +4825,11 @@
\skv@cltrue\skv@testoptb\skv@undefpostsetkeys
}
\skvrobustdef*\skv@undefpostsetkeys{%
- \skvifcsdefFT{\skv@header.@postset}{%
- \skv@err{No postset keys defined for
- '\skvcurrentprefix/\skvcurrentfamily'}\@ehd
+ \skvifcsdefFT{\skvcurrentpath.@postset}{%
+ \skv@err{No postset keys defined for '\skvcurrentpath'}\skv@ehd
}{%
\ifskv@cl\expandafter\global\fi
- \skvcsundef{\skv@header.@postset}%
+ \skvcsundef{\skvcurrentpath.@postset}%
}%
}
@@ -3837,12 +4846,11 @@
\skv@r@movepreposetkeys{#2}{postset}%
}
\skvrobustdef*\skv@r@movepreposetkeys#1#2{%
- \skvifcsdefTF{\skv@header.@#2}{%
+ \skvifcsdefTF{\skvcurrentpath.@#2}{%
\expandafter\skv@filterremoveelements\csname\skv@header
.@#2\endcsname{#1}\skv@getkeyname
}{%
- \skv@err{No preset keys defined for
- '\skvcurrentprefix/\skvcurrentfamily'}\@ehd
+ \skv@err{No preset keys defined for '\skvcurrentpath'}\skv@ehd
}%
}
% \skvundefpreposetkeys[<pref>]{<fam>}
@@ -3853,18 +4861,18 @@
\skv@cltrue\skv@testoptb\skv@undefpreposetkeys
}
\skvrobustdef*\skv@undefpreposetkeys{%
- \skvifcsdefFT{\skv@header.@preset}{%
- \skv@err{No preset keys defined for
- '\skvcurrentprefix/\skvcurrentfamily'}\@ehd
+ \skvifcsdefFT{\skvcurrentpath.@preset}{%
+ \skv@err{No preset keys defined for '\skvcurrentpath'}\skv@ehd
}{%
\ifskv@cl\expandafter\global\fi
- \skvcsundef{\skv@header.@preset}%
+ \skvcsundef{\skvcurrentpath.@preset}%
\ifskv@cl\expandafter\global\fi
- \skvcsundef{\skv@header.@postset}%
+ \skvcsundef{\skvcurrentpath.@postset}%
}%
}
-%% Note about the absence of '(g)save-value-keys':
+%% Note about the absence of \skvsavevaluekeys (save-value-keys):
+%
% All keys have their values saved in the macro '<header>.@value'.
% The value can be accessed via \skvgetvalue of \skvconveyvalue. When
% needed, the value can be taken outside a local group by using \global
@@ -3878,9 +4886,9 @@
\skv@cltrue\skv@testoptb\skv@needvaluekeys
}
\skvrobustdef*\skv@needvaluekeys#1{%
- \skvcommaparse{#1}\skv@tempa{%
+ \skvcommaparse{#1}\skv@prova{%
\ifskv@cl\expandafter\global\fi
- \skvcsdef{\skv@header\skv@tempa.@ndv}{}%
+ \skvcsdef{\skv@header\skv@prova.@ndv}{}%
}%
}
% \skvremoveneedvaluekeys[<pref>]{<fam>}{<keys>}
@@ -3891,9 +4899,9 @@
\skv@cltrue\skv@testoptb\skv@removeneedvaluekeys
}
\skvrobustdef*\skv@removeneedvaluekeys#1{%
- \skvcommaparse{#1}\skv@tempa{%
+ \skvcommaparse{#1}\skv@prova{%
\ifskv@cl\expandafter\global\fi
- \skvcsundef{\skv@header\skv@tempa.@ndv}%
+ \skvcsundef{\skv@header\skv@prova.@ndv}%
}%
}
@@ -3905,9 +4913,9 @@
\skv@cltrue\skv@testoptb\skv@forbidvaluekeys
}
\skvrobustdef*\skv@forbidvaluekeys#1{%
- \skvcommaparse{#1}\skv@tempa{%
+ \skvcommaparse{#1}\skv@prova{%
\ifskv@cl\expandafter\global\fi
- \skvcsdef{\skv@header\skv@tempa.@fbv}{}%
+ \skvcsdef{\skv@header\skv@prova.@fbv}{}%
}%
}
% \skvremoveforbidvaluekeys[<pref>]{<fam>}{<keys>}
@@ -3918,12 +4926,51 @@
\skv@cltrue\skv@testoptb\skv@removeforbidvaluekeys
}
\skvrobustdef*\skv@removeforbidvaluekeys#1{%
- \skvcommaparse{#1}\skv@tempa{%
+ \skvcommaparse{#1}\skv@prova{%
\ifskv@cl\expandafter\global\fi
- \skvcsundef{\skv@header\skv@tempa.@fbv}%
+ \skvcsundef{\skv@header\skv@prova.@fbv}%
+ }%
+}
+% \skvoptionkeys[<pref>]{<fam>}{<keys>}
+\skvrobustdef*\skvoptionkeys{%
+ \skv@clfalse\skv@testoptb{\skv@optionkeys{}}%
+}
+\skvrobustdef*\skvgoptionkeys{%
+ \skv@cltrue\skv@testoptb{\skv@optionkeys{}}%
+}
+% \skvnonoptionkeys[<pref>]{<fam>}{<keys>}
+\skvrobustdef*\skvnonoptionkeys{%
+ \skv@clfalse\skv@testoptb{\skv@optionkeys{non}}%
+}
+\skvrobustdef*\skvgnonoptionkeys{%
+ \skv@cltrue\skv@testoptb{\skv@optionkeys{non}}%
+}
+\skvrobustdef*\skv@optionkeys#1#2{%
+ \skvcommaparse{#2}\skv@prova{%
+ \ifskv@cl\expandafter\global\fi
+ \skvcsdef{\skv@header\skv@prova.@#1opt}{}%
+ }%
+}
+% \skvremoveoptionkeys[<pref>]{<fam>}{<keys>}
+\skvrobustdef*\skvremoveoptionkeys{%
+ \skv@clfalse\skv@testoptb{\skv@removeoptionkeys{}}%
+}
+\skvrobustdef*\skvgremoveoptionkeys{%
+ \skv@cltrue\skv@testoptb{\skv@removeoptionkeys{}}%
+}
+% \skvremovenonoptionkeys[<pref>]{<fam>}{<keys>}
+\skvrobustdef*\skvremovenonoptionkeys{%
+ \skv@clfalse\skv@testoptb{\skv@removenonoptionkeys{non}}%
+}
+\skvrobustdef*\skvgremovenonoptionkeys{%
+ \skv@cltrue\skv@testoptb{\skv@removenonoptionkeys{non}}%
+}
+\skvrobustdef*\skv@removeoptionkeys#1#2{%
+ \skvcommaparse{#2}\skv@prova{%
+ \ifskv@cl\expandafter\global\fi
+ \skvcsundef{\skv@header\skv@prova.@#1opt}%
}%
}
-
% Save the default/initial values of keys:
% \skvsaveinitialvaluekeys[<pref>]{<fam>}{<keys>}
\skvrobustdef*\skvsaveinitialvaluekeys{%
@@ -3934,14 +4981,14 @@
\skv@cltrue\skv@testoptb\skv@saveinitialvaluekeys
}
\skvrobustdef*\skv@saveinitialvaluekeys#1{%
- \skvifcsdefFT{\skv@header.@needini}{%
+ \skvifcsdefFT{\skvcurrentpath.@needini}{%
\edef\skv@tempa{\unexpanded{#1}}%
\skvcsvnormalize\skv@tempa
\ifskv@cl\expandafter\global\fi
- \skvcsedef{\skv@header.@needini}{\skvexpandonce\skv@tempa}%
+ \skvcsedef{\skvcurrentpath.@needini}{\skvexpandonce\skv@tempa}%
}{%
\expandafter\skv@filtermergelist\csname
- \skv@header.@needini\endcsname{#1}\skv@getkeyname
+ \skvcurrentpath.@needini\endcsname{#1}\skv@getkeyname
}%
}
% \skvremovesaveinitialvaluekeys[<pref>]{<fam>}{<keys>}
@@ -3953,12 +5000,11 @@
\skv@cltrue\skv@testoptb\skv@removesaveinitialvaluekeys
}
\skvrobustdef*\skv@removesaveinitialvaluekeys#1{%
- \skvifcsdefFT{\skv@header.@needini}{%
- \skv@err{No save-initial keys defined for
- '\skvcurrentprefix/\skvcurrentfamily'}\@ehd
+ \skvifcsdefFT{\skvcurrentpath.@needini}{%
+ \skv@err{No save-initial keys defined for '\skvcurrentpath'}\skv@ehd
}{%
\expandafter\skv@filterremoveelements\csname
- \skv@header.@needini\endcsname{#1}\skv@getkeyname
+ \skvcurrentpath.@needini\endcsname{#1}\skv@getkeyname
}%
}
% \skvundefsaveinitialvaluekeys[<pref>]{<fam>}
@@ -3970,11 +5016,10 @@
\skv@cltrue\skv@testoptb\skv@undefsaveinitialvaluekeys
}
\skvrobustdef*\skv@undefsaveinitialvaluekeys{%
- \skvifcsdefFT{\skv@header.@needini}{%
- \skv@err{No save-initial keys defined for
- '\skvcurrentprefix/\skvcurrentfamily'}\@ehd
+ \skvifcsdefFT{\skvcurrentpath.@needini}{%
+ \skv@err{No save-initial keys defined for '\skvcurrentpath'}\skv@ehd
}{%
- \csname skv\ifskv@cl g\fi csundef\endcsname{\skv@header.@needini}%
+ \csname skv\ifskv@cl g\fi csundef\endcsname{\skvcurrentpath.@needini}%
}%
}
@@ -3983,14 +5028,14 @@
\skvrobustdef*\skvignorekeys{\skv@clfalse\skv@testoptb\skv@ignorekeys}
\skvrobustdef*\skvgignorekeys{\skv@cltrue\skv@testoptb\skv@ignorekeys}
\skvrobustdef*\skv@ignorekeys#1{%
- \skvifcsdefTF{\skv@header.@ignoredkeys}{%
+ \skvifcsdefTF{\skvcurrentpath.@ignoredkeys}{%
\expandafter\skv@filtermergelist\csname
- \skv@header.@ignoredkeys\endcsname{#1}\skv@getkeyname
+ \skvcurrentpath.@ignoredkeys\endcsname{#1}\skv@getkeyname
}{%
\edef\skv@tempa{\unexpanded{#1}}%
\skvcsvnormalize[,]\skv@tempa
\ifskv@cl\expandafter\global\fi
- \skvcsedef{\skv@header.@ignoredkeys}{\skvexpandonce\skv@tempa}%
+ \skvcsedef{\skvcurrentpath.@ignoredkeys}{\skvexpandonce\skv@tempa}%
}%
}
% \skvremoveignorekeys[<pref>]{<fam>}{<keys>}
@@ -4002,12 +5047,11 @@
\skv@cltrue\skv@testoptb\skv@removeignorekeys
}
\skvrobustdef*\skv@removeignorekeys#1{%
- \skvifcsdefFT{\skv@header.@ignoredkeys}{%
- \skv@err{No ignore keys defined for
- '\skvcurrentprefix/\skvcurrentfamily'}\@ehd
+ \skvifcsdefFT{\skvcurrentpath.@ignoredkeys}{%
+ \skv@err{No ignore keys defined for '\skvcurrentpath'}\skv@ehd
}{%
\expandafter\skv@filterremoveelements\csname
- \skv@header.@ignoredkeys\endcsname{#1}\skv@getkeyname
+ \skvcurrentpath.@ignoredkeys\endcsname{#1}\skv@getkeyname
}%
}
% \skvundefignorekeys[<pref>]{<fam>}
@@ -4019,22 +5063,16 @@
\skv@cltrue\skv@testoptb\skv@undefignorekeys
}
\skvrobustdef*\skv@undefignorekeys{%
- \skvifcsdefFT{\skv@header.@ignoredkeys}{%
- \skv@err{No ignore keys defined for
- '\skvcurrentprefix/\skvcurrentfamily'}\@ehd
+ \skvifcsdefFT{\skvcurrentpath.@ignoredkeys}{%
+ \skv@err{No ignore keys defined for '\skvcurrentpath'}\skv@ehd
}{%
\csname skv\ifskv@cl g\fi csundef\endcsname
- {\skv@header.@ignoredkeys}%
+ {\skvcurrentpath.@ignoredkeys}%
}%
}
-
-% ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-% To add (2012/08/08):
-% \skvoptionkeys
-% \skvnotoptionkeys
-% \skvnewlet\skvnonoptionkeys\skvnotoptionkeys
-%---------------------------------------------------------------
-
+%
+% Adding to the callback of existing keys.
+%
% \skvaddkeycode[<pref>]{<fam>}{<key>}{<precode>}{<postcode>}
\skvrobustdef*\skvaddkeycode{\skv@testoptb\skv@addkeycode}
\skvrobustdef*\skv@addkeycode#1#2#3{%
@@ -4063,251 +5101,263 @@
\skvcsedef{\skv@header\skvcurrentkey.@cbk}{\skvtrimspace{#3}}%
}%
}
-
-% Initialize remaining-keys to empty, for the listed prefixes and families:
-% \skvinitializermkeys{<prefixes>}{<families>}
-\skvrobustdef*\skvinitializermkeys{%
- \skv@clfalse\skv@testst\skv@initializermkeys
-}
-\skvrobustdef*\skvginitializermkeys{%
- \skv@cltrue\skv@testst\skv@initializermkeys
-}
-\skvrobustdef*\skv@initializermkeys#1#2{%
- \skv@usetempst{#1}\skv@tempa
- \skv@usetempst{#2}\skv@tempb
- \skvcommaparse*\skv@tempa\skv@tempa{%
- \skv@makeprefix\skv@tempa
- \skvcommaparse*\skv@tempb\skv@tempb{%
- \skv@makeheader\skv@tempb
- \skvcslet{\skv@header.@rmkeys}\@empty
- \ifskv@cl\skvglobalizecs{\skv@header.@rmkeys}\fi
- }%
- }%
-}
-
-% \skvgetrmkeys[<pref>]{<fam>}<cmd>
-\skvrobustdef*\skvgetrmkeys{\skv@clfalse\skv@testoptb\skv@getrmkeys}
-\skvrobustdef*\skvggetrmkeys{\skv@cltrue\skv@testoptb\skv@getrmkeys}
-\skvrobustdef*\skv@getrmkeys#1{%
- \skvifcsdefTF{\skv@header.@rmkeys}{%
- \skvletcs#1{\skv@header.@rmkeys}%
- \ifskv@cl\global\let#1=#1\fi
- }{%
- \skv@err{No 'rmkeys' for family
- '\skvcurrentprefix/\skvcurrentfamily'}\@ehd
- }%
-}
\skvrobustdef*\skvsetkeys{%
+ \skv@viarootofsetkeystrue
\skv@testopta{\skv@testoptc\skv@setkeys@a}%
}
-% \skv@setkeys@a[<ignore.list>]{<kvlist>}
+\skvrobustdef*\skvsetrmkeys{%
+ \skv@viarootofsetkeystrue
+ \skv@testopta{\skv@testoptc\skv@setrmkeys}%
+}
+\skvrobustdef*\skv@setrmkeys[#1]{%
+ % Only one prefix is allowed here. \skv@testoptc has created
+ % \skvcurrentprefix and \skv@fams.
+ \skvifdefTF\skv@rmkeys{%
+ \skvexpbracenext{\skv@setkeys@a[#1]}\skv@rmkeys
+ }{}%
+}
+% \skv@setkeys@a[<ignored.list>]{<kvlist>}
\skvrobustdef*\skv@setkeys@a[#1]#2{%
% \skvexecuteoptions calls \skv@setkeys@a. So this is the place for
% \skv@insettrue:
\skv@insettrue
% \skv@testoptc has created \skvcurrentprefix and \skv@fams.
- \ifskv@intry\else\skvafterfi
- \skv@getkeynames{#2}\skv@naa
- \fi
+ \skvifdefboolTF{skv@intry}{}{%
+ \skv@getnamesofkeys{#2}\skv@currentnames
+ }%
% Both #1 and #2 will be normalized in \skv@setkeys@b.
\skv@setprepokeys{#1}{preset}%
\skv@setkeys@b{#2}{#1}%
\skv@setprepokeys{#1}{postset}%
\ifnum\skv@setkeysdepth=\skvz@
\skv@insetfalse
+ \skv@viarootofsetkeysfalse
\fi
- % Don't set \let\CurrentOption\@empty here.
+ % Don't do \let\CurrentOption\@empty here.
+}
+\skvnewlet\skv@sav@setkeys@a\skv@setkeys@a
+\skvrobustdef*\skv@badsetkeysinpreset[#1]#2{%
+ \skv@err{%
+ \noexpand\skvsetkeys or \noexpand\skvsetrmkeys can't be nested in a preset
+ \MessageBreak key's callback: this will cause a cyclic call
+ \MessageBreak to \noexpand\skvsetkeys or \noexpand\skvsetrmkeys
+ }\skv@ehd
}
\skvrobustdef*\skv@setprepokeys#1#2{%
- \skv@prepotrue
+ \skv@inprepotrue
+ \let\skv@setkeys@a\skv@badsetkeysinpreset
+ % Preposet keys doesn't use \skv@fams in \skv@setkeys@d; it
+ % branches off to \skv@setkeys@e. Hence the following loop is in
+ % order.
\skvecommaloop*\skv@fams\skvcurrentfamily{%
\skv@makeheader\skvcurrentfamily
- \skvifcsdefFT{\skv@header.@#2}{}{%
- \skv@toksa\expandafter\expandafter\expandafter
- {\csname\skv@header.@#2\endcsname}%
- \skvexpandtwoargs\skv@setkeys@b{\the\skv@toksa}%
- {\skvexpandonce\skv@naa\ifx\skv@naa\@empty\else,\fi
- \unexpanded{#1}}%
+ \skvletcs\reserved@a{\skvcurrentpath.@#2}%
+ \skvifdefFT\reserved@a{}{%
+ \skvexpandtwoargs\skv@setkeys@b{\skvexpandonce\reserved@a}%
+ {\skvaddlist,\skv@currentnames\unexpanded{#1}}%
}%
}%
- \skv@prepofalse
+ \let\skv@setkeys@a\skv@sav@setkeys@a
+ \skv@inprepofalse
}
-
+% \skv@setkeys@b{<kvlist>}{<ignored.list>}
+%
% \skv@keydepth is called in places other than by \skvsetkeys. Hence we
% need an independent \skv@setkeysdepth here.
-% \skv@setkeys@b{<kvlist>}{<ignore.list>}
+%
\skvrobustdef*\skv@setkeys@b#1#2{%
% \skv@setprepokeys calls \skv@setkeys@b. So this is the place to
% advance \skv@setkeysdepth.
\skvgadvanceno\skv@setkeysdepth\@ne
- \ifskv@st
- \ifnum\skv@setkeysdepth=\@ne
- \skvinitializermkeys*\skvcurrentprefix\skv@fams
- \fi
- \fi
\ifnum\skv@setkeysdepth>\skv@stackdepthlimit\relax
\skv@err{\noexpand\skvsetkeys is nested too deeply.
- \MessageBreak Maybe there has been infinite reentry}\@ehd
+ \MessageBreak Maybe there has been infinite reentry}\skv@ehd
\fi
% \skv@na can't be anywhere else, not in \skv@setkeys@a.
\edef\skv@na{\unexpanded{#2}}%
\skvifemptyTF\skv@na{}{\skvcsvnormalize\skv@na}%
- \edef\skv@tempa{\unexpanded{#1}}%
- \skvifemptyTF\skv@tempa{}{\skvkvnormalize\skv@tempa}%
- \def\skv@setkeys@c##1={%
- \skvxifinTF{(}{\detokenize{##1}}{%
- \skvxifinTF{)}{\detokenize{##1}}{%
+ \skvkvparse{#1}\CurrentOption{%
+ \skv@processvalueaslistfalse
+ % Expand the key name twice, in case the key and its value
+ % are hidden in a macro. A maverick might do just that.
+ \expandafter\expandafter\expandafter
+ \skv@setkeys@c\CurrentOption=\skv@novalue=\skv@setkeys@nil
+ }%
+ \skvgadvanceno\skv@setkeysdepth\m@ne
+}
+\skvrobustdef*\skv@setkeys@c#1={%
+ \skvxifinTF{(}{\detokenize{#1}}{%
+ \skvxifinTF{)}{\detokenize{#1}}{%
+ % A pntkey can't carry pointers:
+ \edef\skvcurrentkey{\unexpanded{#1}}%
+ \let\skv@tkey\skvcurrentkey
+ \skv@strippointersfromkey*\skvcurrentkey
+ \skv@strippointersfromvalue*\skvcurrentkey
+ \ifx\skvcurrentvalue\skv@tkey
+ \skv@extractpntkey@atsetkey{#1}%
\def\skv@ispntkey{00}%
- \skv@extr@ctpntkey{##1}\skvcurrentkey\skvcurrentvalue
\ifx\skvcurrentvalue\@empty
\skvnovaluetrue
\else
\skvnovaluefalse
\fi
- }{%
- \skv@err{Key value has '(' but no ')'}
- {The value of a parenthesized key must have both opening
- '(' and closing ')'}%
- }%
+ \else
+ \skv@err{A parenthesized key can't have pointers}\skv@ehd
+ \fi
}{%
- \def\skv@ispntkey{01}%
- \skv@g@tkeyname##1=\skv@nil\skvcurrentkey
+ \skv@err{Key value has '(' but no ')'}
+ {The value of a parenthesized key must have both opening
+ \MessageBreak parenthesis '(' and closing ')'.}%
}%
- \def\skv@prova####1=####2\skv@nil{%
- \skvifcondTF\if\skv@ispntkey\fi{}{%
- \edef\skvcurrentvalue{\skvexpandonce{\@gobble####1}}%
- \ifx\skvcurrentvalue\skv@novaluetoks
- \skvnovaluetrue
- \def\skvcurrentvalue{}%
- \else
- \skvnovaluefalse
- \fi
- \skvexpbracenext\skvifbracedTF\skvcurrentvalue{%
- \skvvaluebracedtrue
- }{%
- % Strip and use pointers from key value:
- \skvexpbracenext\skv@strippointers\skvcurrentvalue
- \skvcurrentvalue
- }%
+ }{%
+ \def\skv@ispntkey{01}%
+ \skv@g@tkeyname#1=\skv@getname@nil\skvcurrentkey
+ }%
+ % ##1=value:
+ \def\skv@prova##1=##2\skv@setkeys@nil{%
+ \skvifplaswTF\skv@ispntkey{%
+ % \skv@extractpntkey@atsetkey would have extracted key name and
+ % value for the pntkey.
+ }{%
+ \edef\skvcurrentvalue{\skvexpandonce{\@gobble##1}}%
+ \ifx\skvcurrentvalue\skv@novaluetoks
+ \skvnovaluetrue
+ \def\skvcurrentvalue{}%
+ \else
+ \skvnovaluefalse
+ \fi
+ \skvexpbracenext\skvifbracedTF\skvcurrentvalue{%
+ \skvvaluebracedtrue
+ }{%
+ \skvvaluebracedfalse
+ \skv@strippointersfromvalue*\skvcurrentvalue
}%
- \ifx\skvcurrentkey\@empty
- \ifx\skvcurrentvalue\@empty\else
- \skv@err{Current key is nil, but you have a value for it:
- \MessageBreak\skvoxdetok\skvcurrentvalue}\@ehd
- \fi
+ }%
+ \ifx\skvcurrentkey\@empty
+ \ifx\skvcurrentvalue\@empty\else
+ \skv@err{Current key is nil, but you have a value for it:
+ \MessageBreak\skvoxdetok\skvcurrentvalue}\skv@ehd
\fi
+ \fi
+ \skvifdefboolTF{skv@processvalueaslist}{%
+ % You can use the pointer '.process list' on the current value to
+ % signify that the value be processed as a list, in the
+ % manner of a list key. This scheme is costlier than defining the
+ % key as a listkey, using \skvlistkey, but it is more versatile.
+ % This allows any key to accept and process a value that is a list,
+ % irrespective of its argument pattern.
+ \skv@processvalueaslist
+ }{%
\edef\CurrentOption{%
\skvcurrentkey
- \ifx\skvcurrentvalue\@empty\else\skvafterfi
- =\skvxonce\skvcurrentvalue
- \fi
+ \ifx\skvcurrentvalue\@empty\else=\skvxonce\skvcurrentvalue\fi
}%
\skv@setkeys@d
}%
- \skv@prova.%
}%
- \skvcommaloop*\skv@tempa\CurrentOption{%
- \skvvaluebracedfalse
- % Expand the key name twice, in case the key and its value
- % are hidden in a macro. A maverick might do just that.
- \expandafter\expandafter\expandafter
- \skv@setkeys@c\CurrentOption=\skv@novalue=\skv@nil
+ \skv@prova.%
+}
+\skvrobustdef*\skv@processvalueaslist{%
+ \skvpushstate\skv@keystate\skv@keydepth
+ \skvifemptyTF\skvcurrentvalue{%
+ \let\CurrentOption\skvcurrentkey
+ \skv@setkeys@d
+ }{%
+ \skvcommaparse*\skvcurrentvalue\skvcurrentvalue{%
+ \edef\CurrentOption{%
+ \skvcurrentkey
+ \ifx\skvcurrentvalue\@empty\else=\skvxonce\skvcurrentvalue\fi
+ }%
+ \skv@setkeys@d
+ }%
}%
- \skvgadvanceno\skv@setkeysdepth\m@ne
+ \skvpopstate\skv@keystate\skv@keydepth
}
-
\skvrobustdef*\skv@setkeys@d{%
- \skv@cnta\@ne
- \skvletcs\skv@tempa{\skv@header.@ignoredkeys}%
+ \begingroup
+ \skv@swatrue
+ \skvxifinTF{,\skvcurrentkey,}{,\skv@na,}{\skv@swafalse}{}%
+ \skvletcs\skv@tempa{\skvcurrentpath.@ignoredkeys}%
\skvifdefTF\skv@tempa{%
- \skvxifinTF{,\skvcurrentkey,}{,\skv@tempa,}{%
- \skv@cnta\skvz@
- }{%
- \skvxifinTF{,\skvcurrentkey,}{,\skv@na,}{\skv@cnta\skvz@}{}%
- }%
- }{%
- \skvxifinTF{,\skvcurrentkey,}{,\skv@na,}{\skv@cnta\skvz@}{}%
- }%
- \skvifnumTF\skv@cnta=\skvz@{}{%
+ \skvxifinTF{,\skvcurrentkey,}{,\skv@tempa,}{\skv@swafalse}{}%
+ }{}%
+ \skvaftergroupifboolFT skv@swa\endgroup{}{%
\skv@kffalse
- \skvifdefboolTF{skv@prepo}{%
+ \skvifdefboolTF{skv@inprepo}{%
\skv@setkeys@e
}{%
- \skvifdefboolTF{skv@intry}{%
- \skv@setkeys@e
+ \skvifdefboolTF{skv@pl}{%
+ % Set the key in all families in which it exists.
+ \skvecommaloop*\skv@fams\skvcurrentfamily{%
+ \skv@makeheader\skvcurrentfamily
+ \skv@setkeys@e
+ }%
}{%
- \skvifdefboolTF{skv@pl}{%
- \skvecommaloop*\skv@fams\skvcurrentfamily{%
- \skv@makeheader\skvcurrentfamily
- \skv@setkeys@e
- % If we don't save rm keys here, the family may change before
- % we get to the next call of \skv@setkeys@f:
- \ifskv@kf\else
- \ifskv@st
- \expandafter\expandafter\expandafter\skv@setkeys@f
- \fi
- \fi
- }%
- }{%
- \skvcommaloop*\skv@fams\skvcurrentfamily{%
- \skv@makeheader\skvcurrentfamily
- \skv@setkeys@e
- \ifskv@kf\skvbreakloop\fi
- }%
+ % Stop searching as soon as the key is found in one family.
+ \skvcommaloop*\skv@fams\skvcurrentfamily{%
+ \skv@makeheader\skvcurrentfamily
+ \skv@setkeys@e
+ \ifskv@kf\skvbreakloop\fi
}%
}%
}%
\skvifdefboolTF{skv@kf}{%
\skvifdefboolTF{skv@inpox}{%
- \ifx\skv@userclassorpackage\skv@documentclass\skvafterfi
- \expandafter\skv@useoption\expandafter{\CurrentOption}%
+ \ifskv@inclass\skvafterfi
+ \expandafter\skv@removeoption\expandafter{\CurrentOption}%
\fi
}{}%
}{%
\skvifdefboolTF{skv@inpox}{%
- \skvifcsdefTF{\skv@header.@famhandler}{%
+ \skvifcsdefTF{\skvcurrentpath.@famhandler}{%
\begingroup
\let\elt\skvexpandonce
\skvexpanded{\endgroup
- \skvnoexpandcs{\skv@header.@famhandler}%
+ \skvnoexpandcs{\skvcurrentpath.@famhandler}%
{\elt\skvcurrentprefix}{\elt\skvcurrentfamily}%
{\elt\skvcurrentkey}{\elt\skvcurrentvalue}%
}%
}{%
- \skvifcsdefTF{skv@dox@\@currname @\@currext}{%
- \skvcsuse{skv@dox@\@currname @\@currext}%
+ \skvifcsdefTF{skv@dox@\@currname.\@currext}{%
+ \skvcsuse{skv@dox@\@currname.\@currext}%
}{%
- \ifx\@currext\@clsextension\else\skvafterfi
- \let\CurrentOption\skvcurrentkey\@unknownoptionerror
+ \ifx\@currext\@clsextension\else
+ \skv@err{%
+ Unknown option '\skvcurrentfullkey'
+ \MessageBreak for \@cls@pkg\space'\@currname'
+ }{%
+ The option '\skvcurrentfullkey'
+ \MessageBreak was not declared in \@cls@pkg\space'\@currname'.
+ \MessageBreak Perhaps you misspelled its name.
+ \MessageBreak Try typing <return> to proceed.
+ }%
\fi
}%
}%
}{%
- \skvifdefboolTF{skv@intry}{%
- % Continue in remaining families. When all the families have
- % been searched and the key isn't found, toggle 'intry' false
- % and raise error.
+ \skvifdefboolTF{skv@st}{%
+ \skv@setkeys@f
}{%
- \skvifdefboolTF{skv@st}{%
- \ifskv@pl
- % In this case we've already saved any rm keys.
- \relax
+ \skvifcsdefTF{\skvcurrentpath.@famhandler}{%
+ \begingroup
+ \let\elt\skvexpandonce
+ \skvexpanded{\endgroup
+ \skvnoexpandcs{\skvcurrentpath.@famhandler}%
+ {\elt\skvcurrentprefix}{\elt\skvcurrentfamily}%
+ {\elt\skvcurrentkey}{\elt\skvcurrentvalue}%
+ }%
+ }{%
+ % \ifskv@viarootofsetkeys is true, then \skvsetkeys is nested
+ % in the callback of a .try key. In that case, throw the exception:
+ \ifskv@intry
+ \ifskv@viarootofsetkeys
+ \skv@err{Key '\skvcurrentfullkey'
+ \MessageBreak is undefined}\skv@ehd
+ \fi
\else
- \expandafter\skv@setkeys@f
+ \skv@err{Key '\skvcurrentfullkey'
+ \MessageBreak is undefined}\skv@ehd
\fi
- }{%
- \skvifcsdefTF{\skv@header.@famhandler}{%
- \begingroup
- \let\elt\skvexpandonce
- \skvexpanded{\endgroup
- \skvnoexpandcs{\skv@header.@famhandler}%
- {\elt\skvcurrentprefix}{\elt\skvcurrentfamily}%
- {\elt\skvcurrentkey}{\elt\skvcurrentvalue}%
- }%
- }{%
- \skv@err{Key '\skvcurrenttriple' is undefined}
- {I have come across an undefined key '\skvcurrentkey'.}%
- }%
}%
}%
}%
@@ -4320,14 +5370,28 @@
}{%
\skv@kftrue
\ifskv@intry\skv@successtrue\fi
+ \ifskv@inpox
+ \skvifcsname\skv@header\skvcurrentkey.@nonopt\then
+ \skv@err{Key '\skvcurrenttriple'
+ \MessageBreak is a non-option key but it has appeared
+ \MessageBreak as a class or package option}\skv@ehd
+ \fi
+ \else
+ \skvifcsname\skv@header\skvcurrentkey.@opt\then
+ \skv@err{Key '\skvcurrenttriple'
+ \MessageBreak is an option key but it has appeared
+ \MessageBreak outside class or package option list}\skv@ehd
+ \fi
+ \fi
\ifskvnovalue
\skvifcsdefTF{\skv@header\skvcurrentkey.@ndv}{%
- \skv@err{Key '\skvcurrenttriple' requires
- \MessageBreak a user value}{Key value needed.}%
+ \skv@err{Key '\skvcurrenttriple'
+ \MessageBreak requires a user value.
+ \MessageBreak Maybe it's a signal key}\skv@ehd
}{%
\skvifcsdefTF{\skv@header\skvcurrentkey.@defa}{%
- \skv@getdefault\skvcurrentprefix\skvcurrentfamily\skvcurrentkey
- \skvcurrentvalue
+ \skv@getdefault\skvcurrentprefix\skvcurrentfamily
+ \skvcurrentkey\skvcurrentvalue
% Check if the default value is braced:
\skvexpbracenext\skvifbracedFT\skvcurrentvalue{}{%
\skvvaluebracedtrue
@@ -4335,103 +5399,61 @@
}{%
\skv@err{No value specified for key
\MessageBreak'\skvcurrenttriple'
- \MessageBreak and no default value}\@ehd
+ \MessageBreak and no default value}\skv@ehd
}%
}%
\else
\skvifcsdefTF{\skv@header\skvcurrentkey.@fbv}{%
\skv@err{Key '\skvcurrenttriple' doesn't
- \MessageBreak accept a user value}{Key value forbidden.}%
+ \MessageBreak accept a user value: key value forbidden.}\skv@ehd
}{}%
\fi
\skvifemptyTF\skvcurrentvalue{}{%
\expandafter\skv@replacepointers\expandafter{\skvcurrentvalue}%
}%
- % Use argument type to possibly expand the argument:
- \def\do##1##2##3{%
- \skvifcsdefTF{\skv@header\skvcurrentkey.@##1arg}{%
- {\noexpand##2}%
- {\skvexpandcsonce{\skv@header\skvcurrentkey.@##1arg}}%
- }{%
- ##3%
- }%
- }%
- % Get key's argument and its expander type:
- \edef\skv@prova{%
- % This ordering is important:
- \do{xx}{\@firstofone}{%
- \do{x2}{\skvexpandtwice}{%
- \do{x1}{\skvexpandonce}{%
- \do{x0}{\unexpanded}{%
- \do{}{\unexpanded}{{\noexpand\unexpanded}{####1}}%
- }%
- }%
- }%
- }%
- }%
- \def\skv@provb##1##2\skv@arg@nil{%
- \edef\skv@temparg{\unexpanded{##2}}%
- \skvstripouterbraces{2}\skv@temparg
- % Apply expander ##1:
- \edef\skvcurrentvalue{\expandafter##1\expandafter{\skvcurrentvalue}}%
- % Strip outer braces of weird arguments, so that the argument can be
- % grabbed by the, possibly multiparametered, callback function:
- \ifx\skv@temparg\skv@simplearg\else\skvafterfi
+ \skvletcs\skv@callback{\skv@header\skvcurrentkey.@cbk}%
+ \skv@getargpattern
+ % 1. Strip outer braces of \skvcurrentvalue, so that the argument can be
+ % grabbed by the, possibly multi-parametered, callback function.
+ % 2. The argument has been obtained from possible explicit definition
+ % of the argument. But if the obtained argument is simple, then the
+ % argument in the key's call maybe more complex:
+ \ifx\skv@argpattern\skv@simplearg\else
+ \ifcsname\skv@header\skvcurrentkey.@listkey\endcsname
+ \skv@err{A listkey must have a one-parameter argument}\skv@ehd
+ \else
\skvstripouterbraces{2}\skvcurrentvalue
\skvvaluebracedfalse
\fi
- }%
- \expandafter\skv@provb\skv@prova\skv@arg@nil
+ \fi
\skvcslet{\skv@header\skvcurrentkey.@value}\skvcurrentvalue
- \skvifcsdefTF{\skv@header\skvcurrentkey.@hp}{%
- \skvexpanded{\skvcslet{\skvexpandcsonce
- {\skv@header\skvcurrentkey.@hp}}}\skvcurrentvalue
- }{}%
\skvpushstate\skv@keystate\skv@keydepth
- \skvletcs\skv@prova{\skv@header\skvcurrentkey.@cbk}%
\expandafter\expandafter\expandafter\def\expandafter\expandafter
- \expandafter\skv@tempcbk\expandafter\skv@temparg\expandafter
- \skeyvaleov\expandafter{\skv@prova}%
- \ifx\skv@temparg\skv@simplearg\skvafterelsei
- \expandafter\skv@tempcbk\expandafter{\skvcurrentvalue}\skeyvaleov
- \else\skvafterfi
- \expandafter\skv@tempcbk\skvcurrentvalue\skeyvaleov
- \fi
+ \expandafter\skv@prova\expandafter\skv@argpattern\expandafter
+ \skeyvaleov\expandafter{\skv@callback}%
+ \skvifxTF\skv@argpattern\skv@simplearg{%
+ \expandafter\skv@prova\expandafter{\skvcurrentvalue}\skeyvaleov
+ }{%
+ \expandafter\skv@prova\skvcurrentvalue\skeyvaleov
+ }%
\skvpopstate\skv@keystate\skv@keydepth
}%
}
% Save rm keys:
\skvrobustdef*\skv@setkeys@f{%
- \edef\skv@prova{%
- \skvcurrentkey
- \ifskvnovalue\else\skvafterfi
- =\skvexpandonce\skvcurrentvalue
- \fi
- }%
\skvexpanded{%
- \skvmergelist\skvnoexpandcs{\skv@header.@rmkeys}%
- {\skvexpandonce\skv@prova}%
+ \skvmergelist\noexpand\skv@rmkeys{\skvexpandonce\CurrentOption}%
% The boolean \ifdirkeys@saveunknownkeys is, by default, false.
% The default value of \dirkeys@unknownkeysmacro is \skvfaillist.
- \ifdirkeys@saveunknownkeys
- \skvmergelist\skvexpandonce\dirkeys@unknownkeysmacro
- {{\skvcurrentprefix}/{\skvcurrentfamily}/%
- {\skvexpandonce\skv@prova}}%
+ \ifindirectkeys
+ \ifdirkeys@saveunknownkeys
+ \skvmergelist\skvexpandonce\dirkeys@unknownkeysmacro
+ {{\skvcurrentprefix}/{\skvcurrentfamily}/%
+ {\skvexpandonce\CurrentOption}}%
+ \fi
\fi
}%
}
-\skvrobustdef*\skvsetrmkeys{\skv@testopta{\skv@testoptc\skv@setrmkeys}}
-\skvrobustdef*\skv@setrmkeys[#1]{%
- % Only one prefix is allowed. \skv@testoptc has created
- % \skvcurrentprefix and \skv@fams.
- \skvcommaloop*\skv@fams\skv@tempa{%
- \skv@makeheader\skv@tempa
- \skvletcs\skv@prova{\skv@header.@rmkeys}%
- \skvifdefTF\skv@prova{%
- \skvexpandbracenext{\skv@setkeys@a[#1]}\skv@prova
- }{}%
- }%
-}
% \skv@getdefault{<pref>}{<fam>}{<key>}{<return.macro>}
\skvrobustdef*\skv@getdefault#1#2#3#4{%
\begingroup
@@ -4468,14 +5490,14 @@
% \skv@testoptc has created \skvcurrentprefix and \skv@fams.
\skvcommaloop*\skv@fams\skv@tempa{%
\skv@makeheader\skv@tempa
- \skvletcs\skv@tempa{\skv@header.@inikv}%
+ \skvletcs\skv@tempa{\skvcurrentpath.@inikv}%
\skvifdefFT\skv@tempa{%
\skv@err{No 'save initial value' keys defined in family
- \MessageBreak'\skvcurrentprefix/\skvcurrentfamily'}\@ehd
+ \MessageBreak'\skvcurrentpath'}\skv@ehd
}{%
- % '\skv@header.@poxkeys' is the list of keys that have been
+ % '\skvcurrentpath.@poxkeys' is the list of keys that have been
% instantiated as current pacakge options.
- \skvletcs\skv@tempc{\skv@header.@poxkeys}%
+ \skvletcs\skv@tempc{\skvcurrentpath.@poxkeys}%
\skvifdefFT\skv@tempc{%
\edef\skv@tempe{%
\skvexpandonce\skv@tempe
@@ -4486,11 +5508,10 @@
% Filter pox (instantiated package/article options) list members:
\def\skv@tempd{}%
\skvcommaloop*\skv@tempa\skv@tempa{%
- \expandafter\skv@g@tkeyname\skv@tempa=\skv@nil\skv@tempb
+ \expandafter\skv@g@tkeyname\skv@tempa=\skv@getname@nil\skv@tempb
\skvxifinTF{,\skvoxdetok\skv@tempb,}{,\skvoxdetok\skv@tempc,}{}{%
\edef\skv@tempd{%
- \skvexpandonce\skv@tempd\ifx\skv@tempd\@empty\else,\fi
- \skvexpandonce\skv@tempa
+ \skvaddlist,\skv@tempd\skvexpandonce\skv@tempa
}%
}%
}%
@@ -4517,7 +5538,7 @@
% Examples:
%
% \skvdefinekeys*+[KVA]{fam1,fam2}[thp@]{%
-% .initialize after define=true,
+% .initialize keys after define=true,
% .save initial values,
% .prepend to every key name=X@,
% .ord/{keya,keyb}/{default-a},
@@ -4542,64 +5563,75 @@
% they've been defined. Leave this as ordinary keys, not zbool keys,
% since the key names contain dot (.). Zapping the spaces in the
% key name will not lead to a boolean of the \ifhp@key:
+
\skvordkey[SKV]{definekeys}{.initialize}[true]{%
\skvifboolvalT{#1}{%
\csname skvdfk@initialize#1\endcsname
}%
}
+
% Save default values as a kv list in macro <header>.@needini:
\skvordkey[SKV]{definekeys}{.save initial values}[true]{%
\skvifboolvalT{#1}{%
\csname skvdfk@saveinitialvalues#1\endcsname
}%
}
-\skvrobustdef*\skvdfkinitialize{\skvdfk@initializetrue}
-\skvrobustdef*\skvdfksaveinitialvalues{\skvdfk@saveinitialvaluestrue}
-\skvrobustdef*\skvsetupdefinekeys#1{%
- \skvsetkeys[SKV]{definekeys}{#1}%
+\skvordkey[SKV]{definekeys}{.parser}[,]{%
+ \skvifntypeTF{#1}{%
+ \def\skvdfk@parser{#1}%
+ \skvstripouterbraces{2}\skvdfk@parser
+ }{%
+ \skv@err{Parser '#1' is invalid; must be a single character}\@ehd
+ }%
}
+\skvrobustdef*\skvsetdefinekeysparser{\def\skvdfk@parser}
+\skvsetdefinekeysparser{,}
+\skvrobustdef*\skvsetupdefinekeys#1{\skvsetkeys[SKV]{definekeys}{#1}}
+
\skvsetupdefinekeys{.initialize=false,.save initial values=false}
-\skvrobustdef*\skvdfkkeytypelet#1{%
+\skvrobustdef*\skvtypecastfordefinekeys#1{%
+ \begingroup
+ \def\skv@tempa{}%
\skvkvparse{#1}\skv@prova{%
- \skvexpbracenext\skv@kvsplit\skv@prova{%
- \skvifcsdefTF{skvdfk@typealias@##1}{%
- \skv@err{Key type alias '##1' already defined}\@ehd
- }{%
- \skvifstrcmpTF{##2}{^skv^}{%
- \skv@err{Key type alias '##1' has no master}\@ehd
+ \skv@okvsplit\skv@prova{%
+ \def\skv@keytypecast####1{%
+ \skvifcsdefTF{skvdfk@typealias@####1}{%
+ \skv@err{Key type alias '####1' already defined}\skv@ehd
}{%
- \skvcsdef{skvdfk@typealias@##1}{##2}%
+ \skvifstrcmpTF{##2}{^skv^}{%
+ \skv@err{Key type alias '####1' has no master}\skv@ehd
+ }{%
+ \edef\skv@tempa{%
+ \skvexpandonce\skv@tempa
+ \skvcsdef{skvdfk@typealias@####1}{##2}%
+ }%
+ }%
}%
}%
+ \skvcommaparse{##1}\skv@prova{%
+ \expandafter\skv@keytypecast\expandafter{\skv@prova}%
+ }%
}%
}%
+ \expandafter\endgroup\skv@tempa
}
-\skvdfkkeytypelet{%
- .singleton=.choice,
+\skvtypecastfordefinekeys{%
+ {.singleton,.state pattern}=.choice,
.exec code=.exec,
- .arg=.argx0,.args=.argx0,
- .arg expanded once=.argx1,
- .arg expanded twice=.argx2,
+ {.arg,.args}=.argx0,
+ .arg expand once=.argx1,
+ .arg expand twice=.argx2,
.arg expanded=.argxx,
- .initialize keys after define=.initialize,
- .initialize after define=.initialize,
- .initialize keys=.initialize,
- .save initial values=.saveini,
- .save initial values of keys=.saveini,
- .prepend to key name=.preptokey,
- .prepend to every key name=.preptokey,
- .append to key name=.apptokey,
- .append to every key name=.apptokey,
- .prepend to callback=.preptocode,
- .prepend to every callback=.preptocode,
- .append to callback=.apptocode,
- .append to every callback=.apptocode,
- .exec after define=.afterdef,
- .after define=.afterdef,
-}
-
-\skvnewdef*\skv@keyparser{,}
+ {.initialize keys after define,.initialize after define,
+ .initialize keys}=.initialize,
+ {.save initial values,.save initial values of keys}=.saveini,
+ {.prepend to key name,.prepend to every key name}=.preptokey,
+ {.append to key name,.append to every key name}=.apptokey,
+ {.prepend to callback,.prepend to every callback}=.preptocode,
+ {.append to callback,.append to every callback}=.apptocode,
+ {.exec after define,.after define}=.afterdef,
+}
\skvnewdef*\skvdfk@afterdefine@hook{}
\skvrobustdef*\skvafterdefinekeys{%
\skvgappendtomacro\skvdfk@afterdefine@hook
@@ -4608,21 +5640,23 @@
\skvifstar{%
\skv@sttrue
\skvifplus
- {\skv@pltrue\skvdfk@testoptb#1}{\skv@plfalse\skvdfk@testoptb#1}%
+ {\skv@pltrue\skvdfk@testoptb#1}
+ {\skv@plfalse\skvdfk@testoptb#1}%
}{%
\skv@stfalse
\skvifplus
- {\skv@pltrue\skvdfk@testoptb#1}{\skv@plfalse\skvdfk@testoptb#1}%
+ {\skv@pltrue\skvdfk@testoptb#1}
+ {\skv@plfalse\skvdfk@testoptb#1}%
}%
}
\skvrobustdef*\skvdfk@testoptb#1{%
- \skv@testopt{\skvdfk@t@stoptb{#1}}\skv@defaultpref
+ \skv@testopt{\skvdfk@t@stoptb{#1}}\skvdefaultprefix
}
\skvrobustdef*\skvdfk@t@stoptb#1[#2]#3{%
\skvxifinTF{,}{\detokenize{#2}}{%
\skv@err{Only one prefix is allowed when calling
\MessageBreak \noexpand\skvdefinekeys or similar commands,
- \MessageBreak but you gave '#2'}\@ehd
+ \MessageBreak but you gave '#2'}\skv@ehd
}{%
% The prefix and families here deserve separate names, to avoid
% confusing them with those required for setting the keys of the
@@ -4639,6 +5673,7 @@
\skv@testopt#1{userhp@}%
}%
}
+\skvrobustdef*\skvedefinekeysifdefinable{\skvedefinekeys*}
% \skvedefinekeys has no stack, since everything is done in a local group.
% It is \skvmakekeys that has a stack.
\skvrobustdef*\skvedefinekeys{%
@@ -4660,13 +5695,13 @@
\def\iftypeis##1\then{%
\ifnum\skv@strcmp{\skvoxdetok\skv@type}{\detokenize{##1}}=\skvz@
}%
- \def\skv@prependtoeverykeyname{}%
- \def\skv@appendtoeverykeyname{}%
- \def\skv@prependtoeverycallback{}%
- \def\skv@appendtoeverycallback{}%
+ \def\do##1{\def##1{}}%
+ \do\skv@prependtoeverykeyname\do\skv@appendtoeverykeyname
+ \do\skv@prependtoeverycallback\do\skv@appendtoeverycallback
+ % Take \skvindeftrue outside the current scope:
+ \def\skv@accumulateonfams{\skvindeftrue}%
\edef\skv@hp{#1}%
\skvdespacecontent\skv@hp
- \def\skv@accumulateonfams{}%
\skv@makeprefix\skvdfk@pref
\edef\skvdfk@currlist{\skvkeepdoubleslashnormalize{#2}}%
\def\skv@definekeys@b##1{%
@@ -4697,21 +5732,23 @@
% 1. No need to reinitialize \skvdfk@afterdefine@hook here. Any changes
% done within the exited group haven't survived outside the group.
% 2. Don't call \skvdfk@initializefalse and \skvdfk@saveinitialvaluesfalse
- % here while in \directkeys: this is reentered for each path.
- \ifskvindirkeys\else
+ % here while in \directkeys: \skvdefinekeys is reentered for each path.
+ % \ifskvdfk@initialize and \ifskvdfk@saveinitialvalues are in the
+ % stack of \directkeys
+ \ifindirectkeys\else
\skvdfk@initializefalse\skvdfk@saveinitialvaluesfalse
\fi
}
\skvrobustdef*\skv@definekeys@c#1{%
\edef\skv@igkeys{%
- \skvifcsname\skv@header.@ignoredkeys\then
- \skvexpandcsonce{\skv@header.@ignoredkeys}%
+ \skvifcsname\skvcurrentpath.@ignoredkeys\then
+ \skvexpandcsonce{\skvcurrentpath.@ignoredkeys}%
\fi
}%
\def\skv@splita##1/##2/{\skv@splitb##1/##2/.}%
\def\skv@splitb##1/##2/##3/##4/##5/##6/##7/##8/##9\skv@split@nil{%
\skvxifinTF{\skv@hashchar}{\detokenize{##2}}{%
- \skv@err{Key name(s) '\detokenize{##2}' contain hash character}\@ehd
+ \skv@err{Key name(s) '\detokenize{##2}' contain hash character}\skv@ehd
}{%
% In case we have, eg, .exec=\def\x{?} instead of .exec/\def\x{?}:
\skvxifinTF{=}{\detokenize{##1}}{%
@@ -4725,7 +5762,7 @@
}%
}%
\skvifcsname skvdfk@typealias@\skv@type\then
- \edef\skv@type{\skvcsuse{skvdfk@typealias@\skv@type}}%
+ \edef\skv@type{\@nameuse{skvdfk@typealias@\skv@type}}%
\fi
\edef\skv@default{\skvexpandonce{\@gobble##3}}%
% To avoid mixing parameter characters in \skv@prova:
@@ -4741,13 +5778,13 @@
}{%
\if\skv@checkkeyexist
\skvifcsname\skv@header##2.@cbk\then
- \skv@err{Key '\skvcurrenttriple' already exists}\@ehd
+ \skv@err{Key '\skvcurrenttriple' already exists}\skv@ehd
\fi
\fi
\if\skv@ischoice
\skv@ifcmdnut\skv@itemfour{%
\skv@err{Empty nominations (state pattern) for
- \MessageBreak choice key '##2'}\@ehd
+ \MessageBreak choice key '##2'}\skv@ehd
}{}%
\fi
\edef\skvdfk@keys{\skvaddlist,\skvdfk@keys##2}%
@@ -4805,7 +5842,7 @@
}%
}%
}%
- \skvexpanded{\skvparselist{\skv@keyparser}}{#1}\skv@prova{%
+ \skvexpanded{\skvparselist{\skvdfk@parser}}{#1}\skv@prova{%
\expandafter\skv@splita\skv@prova
/^skv^/^skv^/^skv^/^skv^/^skv^/^skv^/^skv^/^skv^\skv@split@nil
}%
@@ -4832,7 +5869,7 @@
}
\skvrobustdef*\skv@definekeys@d#1{%
\skvxifinFT{,#1,}{,\skv@validtypes,}{%
- \skv@err{Invalid key type '#1' in \string\skvdefinekeys}\@ehd
+ \skv@err{Invalid key type '#1' in \string\skvdefinekeys}\skv@ehd
}{%
\@tempswatrue
\iftypeis.exec\then
@@ -4897,9 +5934,8 @@
\do\skv@isboolorchoice\do\skv@ischoice\do\skv@needhp\do\skv@isarg
\skvifinTF{,#1,}{,.choice,.choice*,}{%
\skvstripouterbraces{2}\skv@default
- \def\skv@ischoice{00}%
- \def\skv@isboolorchoice{00}%
- \def\skv@needhp{00}%
+ \def\do##1{\def##1{00}}%
+ \do\skv@ischoice\do\skv@isboolorchoice\do\skv@needhp
}{%
\skvifinTF{,#1,}{,.bool,.zbool,.tog,.ztog,}{%
\def\skv@isboolorchoice{00}%
@@ -4914,8 +5950,8 @@
}%
}%
}%
- \skvcommaprocess*\skv@itemtwo\skv@tempa{%
- \skvexpbracenext\skv@strippointers\skv@tempa\skvcurrentkey
+ \skvcommaloop*\skv@itemtwo\skv@tempa{%
+ \skv@strippointersfromkey*\skv@tempa
\edef\skvcurrentkey{%
\skv@prependtoeverykeyname\skvcurrentkey
\skv@appendtoeverykeyname
@@ -4930,14 +5966,14 @@
}%
}%
}{%
- \skvifinFT{,#1,}
- {,.preptokey,.apptokey,.preptocode,.apptocode,}{}{%
+ \skvifinFT{,#1,}{,.preptokey,.apptokey,.preptocode,.apptocode,}{}{%
\let\skv@tempa\skv@itemtwo
- \skvexpbracenext\skv@strippointers\skv@itemtwo\skv@itemtwo
+ \skv@strippointersfromkey*\skv@itemtwo
+ \let\skv@itemtwo\skvcurrentkey
\ifx\skv@tempa\skv@itemtwo\else
\skv@err{The token ||\skvoxdetok\skv@itemtwo||
\MessageBreak shouldn't contain pointers for the
- given key type or requested action}\@ehd
+ given key type or requested action}\skv@ehd
\fi
}%
}%
@@ -4946,7 +5982,9 @@
%
% Assigning arguments within \skvdefinekeys:
%
-% Eg, .arg/{key1,key2}/{#1/#2}
+% Eg, using the type .arg:
+%
+% .arg/{key1,key2}/{#1/#2}
%
\skvrobustdef*\skvdfk@definearg#1#2#3{%
\begingroup
@@ -5000,23 +6038,23 @@
.ord/{.define in all families,.in all families}/true/
\edef\skvmk@inallfams{0\skvifstrcmpTF{#1}{true}{0}{1}}
,
- .ord/.prefix/\skv@defaultpref/
+ .ord/.prefix/\skvdefaultprefix/
\skviflacus#1\then
- \let\skvmk@pref\skv@defaultpref
+ \let\skvmk@pref\skvdefaultprefix
\else
\edef\skvmk@pref{#1}%
\skvstripouterbraces{2}\skvmk@pref
\fi
,
- .ord/{.holder prefix,.hp}/userhp@/\edef\skvmk@hp{#1},
- .ord/{.family,.families}/\@nil/
+ .ord/{.family,.families}/\skv@nil/
\skviflacus#1\then
- \skv@err{Key family is empty\on@line}\@ehd
+ \skv@err{Key family is empty\on@line}\skv@ehd
\else
\edef\skvmk@fams{#1}%
\skvstripouterbraces{2}\skvmk@fams
\fi
,
+ .ord/{.holder prefix,.hp}/userhp@/\edef\skvmk@hp{#1}
}
% Default settings for keys of \skvmakekeys. Presetting keys will be
@@ -5024,10 +6062,9 @@
% necessary to include all the complements in the preset list, but doing
% this will be inefficient.
\skvsetkeys[SKV]{makekeys}{%
- .prefix,.family=^skv^,.hp,.new=false,.define in all families=false,
+ .prefix,.family,.hp,.new=false,.define in all families=false,
.endlinechar=13,.initialize=false,.save initial values=false
}
-
\skvrobustdef*\skvmakekeys{\skv@testopt\skv@makekeys{}}
\skvrobustdef*\skv@makekeys[#1]#2{%
\skvpushfunctions\skvmakekeys{%
@@ -5036,8 +6073,8 @@
\do\ifskvdfk@saveinitialvalues
}\skv@makekeysdepth
\skvsetkeys[SKV]{makekeys}{#1}%
- \ifx\skvmk@fams\@nnil
- \skv@err{No family specified for \string\skvmakekeys}\@ehd
+ \ifx\skvmk@fams\skv@nnil
+ \skv@err{No family specified for \string\skvmakekeys}\skv@ehd
\fi
% The following \begingroup is ended in \skv@definekeys:
\begingroup
@@ -5060,7 +6097,7 @@
\skvrobustdef*\skv@getinnoval#1{%
\begingroup
- \skv@kvosplit{#1}{%
+ \skv@okvsplit{#1}{%
\edef\skv@provb{\detokenize{##2}}%
\skvifxTF\skv@provb\@empty{%
\def\skv@ival{???}%
@@ -5106,7 +6143,7 @@
% \skvsetkeys[KV]{fam}{unknownkey=val}
%
\skvrobustdef*\skvunknownkeyhandler{%
- \skv@testopt\skv@unknownkeyhandler\skv@defaultpref
+ \skv@testopt\skv@unknownkeyhandler\skvdefaultprefix
}
% For each prefix and family, this will define the functions
% \<prefix>/<family>/.@famhandler of 4 parameters (prefix, family,
@@ -5116,7 +6153,7 @@
\skv@makeprefix\skv@tempa
\skvcommaloop{#2}\skv@tempb{%
\skv@makeheader\skv@tempb
- \skvcsdef{\skv@header.@famhandler}##1##2##3##4{#3}%
+ \skvcsdef{\skvcurrentpath.@famhandler}##1##2##3##4{#3}%
}%
}%
}
@@ -5138,38 +6175,40 @@
.ord/{.set in all families,.in all families}/true/
\edef\skvuk@inallfams{\skvifstrcmpTF{#1}{true}{00}{01}}
,
- .ord/.prefix/\skv@defaultpref/
+ .ord/.prefix/\skvdefaultprefix/
\skviflacus#1\then
- \let\skvuk@pref\skv@defaultpref
+ \let\skvuk@pref\skvdefaultprefix
\else
\edef\skvuk@pref{#1}%
\skvstripouterbraces{2}\skvuk@pref
\fi
,
- .ord/{.family,.families}/\@nil/
+ .ord/{.family,.families}/\skv@nil/
\skviflacus#1\then
- \skv@err{Key family is empty\on@line}\@ehd
+ \skv@err{Key family is empty\on@line}\skv@ehd
\else
\edef\skvuk@fams{#1}%
\skvstripouterbraces{2}\skvuk@fams
\fi
,
- .ord/{.path,paths}/\@nil/
+ .ord/{.path,paths}/\skv@nil/
\skvifblankTF{#1}{%
- \skv@err{Key family is empty\on@line}\@ehd
+ \skv@err{Key family is empty\on@line}\skv@ehd
}{%
- \edef\skvuk@paths{#1}%
- \skvstripouterbraces{2}\skvuk@paths
- \skvexpbracenext\skv@slashsplit\skvuk@paths{%
- \skvsetkeys[SKV]{usekeys}{.prefix=##1,.family=##2}%
- }%
+ \edef\skv@tempa{#1}%
+ \ifx\skv@tempa\skv@nnil
+ \skv@err{No path specified for \string\skvusekeys}\skv@ehd
+ \else
+ \skvstripouterbraces{2}\skv@tempa
+ \skv@splitpath@a\skv@tempa\skvuk@pref\skvuk@fams
+ \fi
}%
,
}
% Default settings for keys of \skvusekeys:
\skvsetkeys[SKV]{usekeys}{%
- .prefix,.family=^skv^,.set in all families=false,.save rm=false%
+ .prefix,.family,.set in all families=false,.save rm=false%
}
\skvrobustdef*\skvusekeys{\skv@testopt\skv@usekeys{}}
@@ -5178,8 +6217,8 @@
\do\skvuk@fams\do\skvuk@pref\do\skvuk@inallfams\do\skvuk@saverm
}\skv@usekeysdepth
\skvsetkeys[SKV]{usekeys}{#1}%
- \ifx\skvuk@fams\@nnil
- \skv@err{No family specified for \string\skvusekeys}\@ehd
+ \ifx\skvuk@fams\skv@nnil
+ \skv@err{No family specified for \string\skvusekeys}\skv@ehd
\fi
\skvexpanded{%
\noexpand\skvsetkeys\if\skvuk@saverm*\fi\if\skvuk@inallfams+\fi
@@ -5190,14 +6229,15 @@
%++++++++++ Utilities for handlers of the macro \directkeys +++++++++++%
-\skvnewlet\handlereov\relax
+\skvnewlet\skvhandlereov\relax
% Undefine \dirkeys@handler@, in case a handler function is called
% without the handler name. Handler functions usually require
% 'dirkeys@handler@<handler.name>'.
-\skvcsundef{dirkeys@handler@}
+\skvundef\dirkeys@handler@
+\skvrobustdef*\skvsetdirectkeysparser{\def\dirkeys@parser}
+\skvsetdirectkeysparser{,}
\skvrobustdef*\directkeys{\skv@testst\skv@dirkeys@parse@a}
-\skvnewlet\dirkeys\directkeys
\skvrobustdef*\skv@dirkeys@parse@a{%
\begingroup
\ifskv@tempst\endlinechar\m@ne\fi
@@ -5206,121 +6246,121 @@
\skvrobustdef*\skv@dirkeys@parse@b#1{%
\endgroup
\skvpushstate\skv@dirkeys@state\dirkeys@depth
- \skvindirkeystrue
- % Note 1: Initialise all lists to empty. This note is referred to
- % somewhere: don't delete its number.
- \def\dirkeys@prefixlist{}%
- \def\dirkeys@familylist{}%
+ \indirectkeystrue
+ \def\dirkeys@pathlist{}%
\def\dirkeys@holderprefixtoks{}%
\dirkeys@saveunknownkeysfalse
\skvdfk@initializefalse
\skvdfk@saveinitialvaluesfalse
\edef\skv@tempa{\unexpanded{#1}}%
\skvstripouterbraces{2}\skv@tempa
+ % Normalize with respect to equality (=) and comma (,), since
+ % \skvkvnormalize can't normalize with respect to \dirkeys@parser
+ % that isn't comma (,). \skvparselist will normalize with respect
+ % to \dirkeys@parser:
\skvkvnormalize\skv@tempa
\def\skv@dirkeys@split##1=##2=##3\dirkeys@nil{%
\edef\skv@tempa{\unexpanded{##2}}%
\skvstripouterbraces{2}\skv@tempa
\skvdespacecontent\skv@tempa
- % Get the first token, to test if it's \dirkeys. If it is, then
+ % Get the first token, to test if it's \directkeys. If it is, then
% we have a nested \dirkeys:
- \expandafter\skvifxTF\skv@car##1x\car@nil\dirkeys{%
+ \expandafter\skvifxTF\skv@car##1x\car@nil\directkeys{%
\skvifemptyTF\skv@tempa{%
##1\relax
}{%
\skv@err{Something wrong with use of \string\dirkeys:
- \MessageBreak equals ('=') found after \string\dirkeys}\@ehd
+ \MessageBreak equals ('=') found after \string\dirkeys}\skv@ehd
}%
}{%
\skv@ensurehandlerdot{##1}%
\skvifcsdefTF{dirkeys@handler@##1}{%
\csname dirkeys@handler@##1\expandafter\endcsname
- \skv@tempa\handlereov
+ \skv@tempa\skvhandlereov
}{%
- \skv@err{Unknown handler '\detokenize{##1}'\MessageBreak
- in command \string\dirkeys, or no '=' sign}\@ehd
+ \skv@err{Unknown handler '\detokenize{##1}'
+ \MessageBreak in command \string\directkeys, or no '=' sign
+ \MessageBreak after handler name}\skv@ehd
}%
}%
}%
- \skvexpanded{\skvdolist*{\skv@keyparser}}\skv@tempa\skv@tempa{%
+ % Normalize with respect to \dirkeys@parser:
+ \skvexpanded{\skvparselist*{\dirkeys@parser}}\skv@tempa\skv@tempa{%
\expandafter\skv@dirkeys@split\skv@tempa==\dirkeys@nil
}%
- \skvindirkeysfalse
+ \indirectkeysfalse
\skvpopstate\skv@dirkeys@state\dirkeys@depth
}
-\skvrobustdef*\dirkeys@setdefaultroot{%
- \ifx\dirkeys@familylist\@empty
+\skvrobustdef*\dirkeys@setdefaultpath{%
+ \ifx\dirkeys@pathlist\@empty
\ifskv@inopt
- \edef\dirkeys@familylist{\@currname.\@currext}%
+ \edef\dirkeys@pathlist{%
+ \noexpand\skv@pathdo{KV}{\@currname.\@currext}%
+ }%
\else
- \skv@err{No key's family can be empty}\@ehd
+ \skv@err{No key can have empty or nil path/family}\skv@ehd
\fi
\fi
- \ifx\dirkeys@prefixlist\@empty
- \let\dirkeys@prefixlist\skv@defaultpref
- \fi
\ifx\dirkeys@holderprefixtoks\@empty
\def\dirkeys@holderprefixtoks{user@}%
\fi
}
-\skvrobustdef*\dirkeys@getrootlist{%
- \def\skv@rootlist{}%
- \def\do##1##2{%
- \edef\skv@rootlist{%
- \skvexpandonce\skv@rootlist
- \noexpand\skv@doonroot{##1}{##2}%
- }%
- }%
- \dirkeys@getcurrentroots\do
+\skvnewnumbers[skv@]{pathdepth}
+\skvrobustdef*\skv@pushpathdo{%
+ \edef\skv@pathdepth{\the\numexpr\skv@pathdepth+1}%
+ \skvcslet{skv@pathdo@\romannumeral\skv@pathdepth}\skv@pathdo
+}
+\skvrobustdef*\skv@poppathdo{%
+ \skvletcs\skv@pathdo{skv@pathdo@\romannumeral\skv@pathdepth}%
+ \edef\skv@pathdepth{\the\numexpr\skv@pathdepth-1}%
}
-\skvrobustdef*\dirkeys@getcurrentroots#1{%
+\skvrobustdef*\dirkeys@dodefinekeys#1#2{%
\begingroup
- \dirkeys@setdefaultroot
+ % #2 may contain parameter characters that may be confused with
+ % ##1 and ##2 below. Hence we put it in the macro \skv@tempb.
+ % Note: Ignored keys are omitted by \skvdefinekeys.
+ \edef\skv@tempb{\unexpanded{#2}}%
\def\skv@tempa{}%
- \skvcommaloop*\dirkeys@prefixlist\skv@prova{%
- \skvcommaloop*\dirkeys@familylist\skv@provb{%
- \edef\skv@tempa{\skvexpandonce\skv@tempa
- \unexpanded{#1}{\skv@prova}{\skv@provb}}%
+ \def\skv@pathdo##1##2{%
+ \edef\skv@tempa{%
+ \skvexpandonce\skv@tempa
+ \skvdefinekeys#1[##1]{##2}%
+ [\dirkeys@holderprefixtoks]{\skvexpandonce\skv@tempb}%
}%
}%
+ \dirkeys@pathlist
\expandafter\endgroup\skv@tempa
}
-
-\skvrobustdef*\dirkeys@dodefinekeys#1{%
+% \dirkeys@definetypekeys{<type>}{<star.or.empty>}{<keylist>}
+\skvrobustdef*\dirkeys@definetypekeys#1#2#3{%
\begingroup
- % #1 may contain parameter characters that may be confused with
- % ##1 and ##2 below. Hence we put it in the macro \skv@tempb.
- % Note: Ignored keys are omitted by \skvdefinekeys.
- \edef\skv@tempb{\unexpanded{#1}}%
\def\skv@tempa{}%
- \def\do##1##2{%
+ \skvexpanded{\skvparselist{\skvdfk@parser}}{#3}\skv@prova{%
\edef\skv@tempa{%
\skvexpandonce\skv@tempa
- \skvdefinekeys\ifskv@handlerswa*\fi[##1]{##2}%
- [\dirkeys@holderprefixtoks]{\skvexpandonce\skv@tempb}%
+ \ifx\skv@tempa\@empty\else\skvdfk@parser\fi
+ .#1/\skvexpandonce\skv@prova
}%
}%
- \dirkeys@getcurrentroots\do
- \expandafter\endgroup\skv@tempa
+ \skvexpanded{\endgroup
+ \dirkeys@dodefinekeys{#2}{\skvexpandonce\skv@tempa}%
+ }%
}
-\skvrobustdef*\dirkeys@dosetkeys#1#2{%
+\skvrobustdef*\dirkeys@setkeys#1#2#3#4{%
\begingroup
% #1 may contain parameter characters that may be confused with
% ##1 and ##2 below. Hence we put it in the macro \skv@tempb:
- \edef\skv@tempb{\unexpanded{#1}}%
+ \edef\skv@tempb{\unexpanded{#4}}%
\def\skv@tempa{}%
- \def\do##1##2{%
+ \def\skv@pathdo##1##2{%
\edef\skv@tempa{%
\skvexpandonce\skv@tempa
- #2\ifdirkeys@saveunknownkeys*\else\ifskv@handlerswa*\fi\fi
+ #3\ifdirkeys@saveunknownkeys*\else#1\fi
[##1]{##2}[\skvcsuse{##1/##2/.@ignoredkeys}]%
- % #1 may contain unbalanced conditionals; hence the need for
- % \skvifdefboolTF here. When setting 'rm keys', then no
- % key list is needed here.
- \skvifdefboolTF{skv@handlerswb}{}{{\skvexpandonce\skv@tempb}}%
+ \skvifstrcmpTF{#2}{rm}{}{{\skvexpandonce\skv@tempb}}%
}%
}%
- \dirkeys@getcurrentroots\do
+ \dirkeys@pathlist
\expandafter\endgroup\skv@tempa
}
@@ -5330,16 +6370,13 @@
\begingroup
\def\skv@tempd{}%
% ##1=prefix, ##2=family
- \def\do##1##2{%
+ \def\skv@pathdo##1##2{%
\def\skv@tempb{}%
\skvletcs\skv@igkeys{##1/##2/.@ignoredkeys}%
\skvifdefTF\skv@igkeys{}{\def\skv@igkeys{}}%
\skvcommaparse{#1}\skv@tempa{%
\skvxifinTF{,\skvoxdetok\skv@tempa,}{,\skvoxdetok\skv@igkeys,}{}{%
- \edef\skv@tempb{%
- \skvexpandonce\skv@tempb\ifx\skv@tempb\@empty\else,\fi
- \skvexpandonce\skv@tempa
- }%
+ \edef\skv@tempb{\skvaddlist,\skv@tempb\skvexpandonce\skv@tempa}%
}%
}%
\edef\skv@tempd{%
@@ -5349,47 +6386,30 @@
}%
}%
}%
- \dirkeys@getcurrentroots\do
+ \dirkeys@pathlist
\expandafter\endgroup\skv@tempd
}
% \dirkeys@dolistedkeys@b{<callback>}
\skvrobustdef*\dirkeys@dolistedkeys@b#1{%
\begingroup
- % ##1=prefix, ##2=family
\def\skv@tempa{}%
- \def\do##1##2{%
+ % ##1=prefix, ##2=family
+ \def\skv@pathdo##1##2{%
\edef\skv@tempa{%
\skvexpandonce\skv@tempa
\unexpanded{\skv@makeprefix{##1}\skv@makeheader{##2}#1}%
}%
}%
- \dirkeys@getcurrentroots\do
+ \dirkeys@pathlist
\expandafter\endgroup\skv@tempa
}
-\skvrobustdef*\skv@getexpander#1{%
- \begingroup
- \edef\skv@prova{\skvtrimspace{#1}}%
- \def\skv@provb##1{%
- \def\skv@provb####1##1####2####3\skv@nil{%
- \endgroup
- % Don't use \let for the next definition:
- \def\skvexpander{####2}%
- \ifx\skvexpander\@nnil
- \skv@err{Unknown expansion type '\detokenize{##1}'}\@ehd
- \fi
- }%
- \skv@provb x0{\unexpanded}x1{\skvexpandonce}x2{\skvexpandtwice}%
- xx{\@iden}##1{\@nil}\skv@nil
- }%
- \expandafter\skv@provb\expandafter{\skv@prova}%
-}
\skvrobustdef*\skv@getmaintoks#1#2{%
\def\skv@prova##1#2##2#2##3\skv@nil{%
\edef\skvcurrentmaintoks{\skvtrimspace{##1}}%
\skvstripouterbraces{2}\skvcurrentmaintoks
\ifx\skvcurrentmaintoks\@empty
- \skv@err{No main key in '\detokenize{#1}'}\@ehd
+ \skv@err{No main key in '\detokenize{#1}'}\skv@ehd
\fi
\edef\skvcurrentsub{\unexpanded{##2}}%
\ifx\skvcurrentsub\skv@novaluetoks
@@ -5402,16 +6422,15 @@
\skv@prova#1#2\skv@novalue#2\skv@nil
}
-% Pushing and popping prefix, family or holder prefix.
+% Pushing and popping path or holder prefix.
%
-\skvnewnumbers[dirkeys@meta]{prefixdepth,familydepth,hpdepth}
+\skvnewnumbers[dirkeys@meta]{pathdepth,hpdepth}
\skvrobustdef*\dirkeys@pushmeta#1{%
- \skvifcase\skvifstrcmpTF{#1}%
- {prefix}{\def\@elt{prefixlist}}%
- {family}{\def\@elt{familylist}}%
- {hp}{\def\@elt{holderprefixtoks}}%
+ \skvifcasse{#1}
+ case{path}{\def\@elt{pathlist}}
+ case{hp}{\def\@elt{holderprefixtoks}}
\elsedo
- \skv@err{Unknown meta type '#1'}\@ehd
+ \skv@err{Unknown meta type '#1'}\skv@ehd
\endif
\skvaftercs\skvgadvanceno{dirkeys@meta#1depth}\@ne
\edef\skv@elt{\skvrom\csname dirkeys@meta#1depth\endcsname}%
@@ -5419,11 +6438,10 @@
}
\skvrobustdef*\dirkeys@popmeta#1{%
\skvifcase\skvifstrcmpTF{#1}%
- {prefix}{\def\@elt{prefixlist}}%
- {family}{\def\@elt{familylist}}%
+ {path}{\def\@elt{pathlist}}%
{hp}{\def\@elt{holderprefixtoks}}%
\elsedo
- \skv@err{Unknown meta type '#1'}\@ehd
+ \skv@err{Unknown meta type '#1'}\skv@ehd
\endif
\edef\skv@elt{\skvrom\csname dirkeys@meta#1depth\endcsname}%
\skvcsletcs{dirkeys@\@elt}{dirkeys@\@elt @meta@\skv@elt}%
@@ -5432,8 +6450,8 @@
% Assigning admissible values to keys. The handlers here are:
%
-% .state pattern, .state pattern expanded, .state pattern expanded once,
-% .state pattern expanded twice.
+% .state pattern, .state pattern expanded, .state pattern expand once,
+% .state pattern expand twice.
%
% \dirkeys@savechoice{<list>}{<expander.type>}
%
@@ -5448,7 +6466,6 @@
%
\skvrobustdef*\dirkeys@savechoice#1#2{%
\begingroup
- \dirkeys@getrootlist
\def\skv@tempd{}%
\edef\skv@tempa{\unexpanded{#1}}%
\skvcsvnormalize[/]\skv@tempa
@@ -5460,7 +6477,7 @@
\skvrobustdef*\dirkeys@s@vechoice#1#2{%
\skv@getmaintoks{#1}{/}%
\skvkvnormalize\skvcurrentsub
- \def\skv@doonroot##1##2{%
+ \def\skv@pathdo##1##2{%
\skvletcs\skv@igkeys{##1/##2/.@ignoredkeys}%
\skvifdefTF\skv@igkeys{}{\def\skv@igkeys{}}%
\skvcommaparse*\skvcurrentmaintoks\skv@tempb{%
@@ -5490,11 +6507,11 @@
}%
}%
}%
- \skv@rootlist
+ \dirkeys@pathlist
}
% \dirkeys@executechoice{<expansion.type>}{<curr.value>}{<choices.and.cbks>}
\skvrobustdef*\dirkeys@executechoice#1#2#3{%
- \skv@getexpander{#1}%
+ \skv@getexpander@b{#1}%
\edef\skv@prova{\skvexpander{#2}}%
\skvdespacecontent\skv@prova
\def\do##1##2##3\skv@nil{%
@@ -5503,7 +6520,7 @@
##2%
}{%
\skvifblankTF{##3}{%
- \skv@err{No choice match found for key '\skvcurrentkey'}\@ehd
+ \skv@err{No choice match found for key '\skvcurrentkey'}\skv@ehd
}{%
\do##3\skv@nil
}%
@@ -5512,81 +6529,91 @@
\do#3\skv@nil
}
+% Slot/style keys represent a limited signal-slot (or subject-observer)
+% concept from Java.
+%
% The handlers here are:
%
-% .style, .style expanded, .style expanded once, .style expanded twice.
+% .slot, .slot value expanded, .slot expand once, .slot expand twice,
+% .prepend slot, .prepend slot value expanded, .prepend slot expand once,
+% .prepend slot expand twice, .append slot, .append slot value expanded,
+% .append slot expand once, .append slot expand twice
%
% Note that the handlers are preceded by 'append' or 'prepend'.
%
-% \dirkeys@savestyle{<list>}{<append.or.prepend>}{<expander.type>}
+% \dirkeys@saveslots{<list>}{<append.or.prepend>}{<expander.type>}
%
% 1. <list> has the form
%
-% {<main key1>,...,<main key-n>}/{<style1=val1>,...,<style-n=val-n>}
+% {<signal key1>,...,<signal key-n>}/{<slot1=val1>,...,<slot-n=val-n>}
% ,...,
-% {<main key1>,...,<main key-n>/{<style1=val1>,...,<style-n=val-n>}
+% {<signal key1>,...,<signal key-n>/{<slot1=val1>,...,<slot-n=val-n>}
%
-% 2. Here the styles are linked with each main key. When the main key is
-% set, the associated styles will be set with the given values.
+% 2. Here the slots are linked with each signal key. When the signal key is
+% set, the associated slots will be set with the given values.
%
% 3. Examples:
%
-% a) The following example means that keyc and keyd are representations
-% for the actions on their right (ie, for setting 'keya=\someright,
-% keyb=\keybval') when keyc or keyd is set. The values of keya and
-% keyb will be expanded twice before the keys are set:
+% a) The following example means that keyc and keyd are signals
+% (representations for the actions on their right, ie, for setting
+% the slots 'keya=\someright, keyb=\keybval' when keyc or keyd is set).
+% The values of keya and keyb will be expanded twice before the
+% keys are set:
%
-% .append style expand twice={keyc,keyd}/{keya=\someright,keyb=\keybval}.
+% .append slot expand twice={keyc,keyd}/{keya=\someright,keyb=\keybval}.
%
% b) In the following example, #1 will be the value of keye and/or keyf
% when they're set. The values of keye and keyf will be fully expanded
% before they're assigned to keyc and keyd:
%
-% .prepend style expanded={keye,keyf}/{keyc=#1,keyd=#1}
+% .prepend slot value expanded={keye,keyf}/{keyc=#1,keyd=#1}
%
-\skvrobustdef\dirkeys@savestyle#1#2#3{%
+\skvrobustdef*\dirkeys@saveslots#1#2#3{%
\begingroup
- \dirkeys@getrootlist
- \skv@getexpander{#3}%
+ \skv@getexpander@b{#3}%
\def\skv@tempd{}%
\edef\skv@tempa{\unexpanded{#1}}%
\skvcsvnormalize[/]\skv@tempa
\skvcommaparse*\skv@tempa\skv@tempa{%
- \skvexpbracenext\dirkeys@s@vestyle\skv@tempa{#2}%
+ \skvexpbracenext\dirkeys@s@veslots\skv@tempa{#2}%
}%
\expandafter\endgroup\skv@tempd
}
-\skvrobustdef\dirkeys@s@vestyle#1#2{%
+\skvrobustdef*\dirkeys@s@veslots#1#2{%
\skv@getmaintoks{#1}{/}%
\skvcsvnormalize\skvcurrentmaintoks
\skvkvnormalize\skvcurrentsub
- \def\skv@doonroot##1##2{%
+ \def\skv@pathdo##1##2{%
\skvletcs\skv@igkeys{##1/##2/.@ignoredkeys}%
\skvifdefTF\skv@igkeys{}{\def\skv@igkeys{}}%
- \skvcommaloop*\skvcurrentmaintoks\skv@maintoks{%
- \skvxifinTF{,\skv@maintoks,}{,\skv@igkeys,}{}{%
- \skvifcsdefTF{##1/##2/\skv@maintoks.@cbk}{}{%
- % Link keys should always be set with a value. If they were
- % undefined before being designated as a link key, then
- % clearly they should have no default.
+ \skvcommaloop*\skvcurrentmaintoks\skv@signalkey{%
+ \skvxifinTF{,\skv@signalkey,}{,\skv@igkeys,}{}{%
+ \skvifcsdefTF{##1/##2/\skv@signalkey.@cbk}{}{%
+ % Signal keys should always be set with a value. If they were
+ % undefined before being designated as a signal key, then
+ % clearly they should have no default. The empty callback will
+ % later be replaced by signal emitters to the slots.
\edef\skv@tempd{%
\skvexpandonce\skv@tempd
- \skvordkey[##1]{##2}{.need value{\skv@maintoks}}{}%
+ \skvordkey[##1]{##2}{.need value{\skv@signalkey}}{}%
}%
}%
- \def\skv@stylelist{}%
+ % Insert expanders in the sub list:
+ \def\skv@slotlist{}%
\skvcommaloop*\skvcurrentsub\skv@tempa{%
- \skv@kvosplit\skv@tempa{%
- \skvxifstrcmpTF{\skv@maintoks}{####1}{%
- \skv@err{Linking key '####1' to itself}\@ehd
+ \skv@okvsplit\skv@tempa{%
+ \skvxifstrcmpTF{\skv@signalkey}{####1}{%
+ \skv@err{Linking key '####1' to itself}\skv@ehd
}{%
+ % Slot keys must always be predefined, otherwise the signal
+ % will be useless:
\skvifcsdefTF{##1/##2/####1.@cbk}{}{%
- \skv@err{Style key '####1' is undefined}\@ehd
+ \skv@err{Slot key '####1' is undefined}\skv@ehd
}%
}%
\skvxifinTF{,####1,}{,\skv@igkeys,}{}{%
- \edef\skv@stylelist{%
- \skvaddlist,\skv@stylelist\unexpanded{####1}=%
+ \edef\skv@slotlist{%
+ \skvaddlist,\skv@slotlist\unexpanded{####1}=%
\skvexpandonce\skvexpander{\unexpanded{####2}}%
}%
}%
@@ -5595,26 +6622,37 @@
}%
\edef\skv@tempd{%
\skvexpandonce\skv@tempd
- % The styles contain value expanders \@firstofone, \unexpanded, etc.
+ % The slots contain value expanders \@firstofone, \unexpanded, etc.
% They will be expanded by the next \skvexpanded when the main key
% is set.
- \skvifstrcmpTF{#2}{app}\skvappendkeycode\skvprependkeycode
- [##1]{##2}{\skv@maintoks}%
- {\skvexpanded{\skvsetkeys[##1]{##2}%
- {\skvexpandonce\skv@stylelist}}}%
+ \skvifstrcmpTF{#2}{app}{\skvappendkeycode}{\skvprependkeycode}%
+ [##1]{##2}{\skv@signalkey}{%
+ % Signal keys shouldn't be preset, to avoid cyclic setting
+ % of keys. See note above.
+ \noexpand\skvifdefboolTF{skv@inprepo}{%
+ \noexpand\skv@signalpreseterr
+ }{%
+ % The following \skvexpanded works on expanders of slot values:
+ \skvexpanded{\skvsetkeys[##1]{##2}{\skvexpandonce\skv@slotlist}}%
+ }%
+ }%
}%
}%
}%
- \skv@rootlist
+ \dirkeys@pathlist
}
%% +++++++++++++++ Linking keys:
%
% The handlers here are:
%
-% .link, .link expanded, .link expanded once, .link expanded twice.
+% .link, .link expanded, .link expand once, .link expand twice,
+% .prepend link, .prepend link expanded, .prepend link expand once,
+% .prepend link expand twice,
+% .append link, .append link expanded, .append link expand once,
+% .append link expand twice
%
-% \dirkeys@savestyle{<list>}{<append.or.prepend>}{<expander.type>}
+% \dirkeys@savelinks{<list>}{<append.or.prepend>}{<expander.type>}
%
% 1. <list> has the form
%
@@ -5632,12 +6670,12 @@
%
% This is equivalent to:
%
-% .style={{keyb,keyc}/keya=#1}
+% .slot={{keyb,keyc}/keya=#1} OR .style={{keyb,keyc}/keya=#1}
%
% This will link keyb and keyc to keya, such that when keyb and
% keyc are set, keya too will be set with their values.
%
-\skvrobustdef\dirkeys@savelink#1#2#3{%
+\skvrobustdef*\dirkeys@savelinks#1#2#3{%
\begingroup
\def\skv@tempe{}%
\edef\skv@tempa{\unexpanded{#1}}%
@@ -5648,33 +6686,103 @@
\def\skv@tempd{}%
\skvcommaparse*\skvcurrentsub\skv@tempb{%
\edef\skv@tempd{%
- \skvexpandonce\skv@tempd\ifx\skv@tempd\@empty\else,\fi
- \skvexpandonce\skv@tempb=####1%
+ \skvaddlist,\skv@tempd\skvexpandonce\skv@tempb=####1%
}%
}%
\edef\skv@tempe{%
- \skvexpandonce\skv@tempe\ifx\skv@tempe\@empty\else,\fi
+ \skvaddlist,\skv@tempe
{\skvexpandonce\skvcurrentmaintoks}/{\skvexpandonce\skv@tempd}%
}%
}%
- \expandafter\endgroup\expandafter\dirkeys@savestyle
+ \expandafter\endgroup\expandafter\dirkeys@saveslots
\expandafter{\skv@tempe}{#2}{#3}%
}
+% ++++++++++++ Storing values of keys:
+%
+% The handlers here are:
+%
+% .store value in, .store expanded value in, .store expanded once value in,
+% .store expanded twice value in.
+%
+% \dirkeys@savestores{<list>}{<expander.type>}
+%
+% 1. <list> has the form
+%
+% <key-1>/<cmd-1>,...,<key-n>/<cmd-n>
+%
+% 2. Examples:
+%
+% .store expanded twice value in={keyc/\valc,keyd/\vald}
+%
+\skvrobustdef*\dirkeys@savestores#1#2{%
+ \begingroup
+ \skv@getexpander@b{#2}%
+ \def\skv@tempd{}%
+ \edef\skv@tempa{\unexpanded{#1}}%
+ \skvcsvnormalize[/]\skv@tempa
+ \skvcommaparse*\skv@tempa\skv@tempa{%
+ \skv@oslashsplit\skv@tempa{%
+ \skvifstrcmpTF{##2}{^skv^}{%
+ \skv@err{No holder commands for key(s) '\detokenize{##1}'}\skv@ehd
+ }{%
+ \skvcommaparse{##1}\skv@tempa{%
+ \skvexpbracenext\dirkeys@s@vestore\skv@tempa{##2}%
+ }%
+ }%
+ }%
+ }%
+ \expandafter\endgroup\skv@tempd
+}
+\skvrobustdef*\dirkeys@s@vestore#1#2{%
+ \def\skv@pathdo##1##2{%
+ \skvletcs\skv@igkeys{##1/##2/.@ignoredkeys}%
+ \skvifdefTF\skv@igkeys{}{\def\skv@igkeys{}}%
+ \skvxifinTF{,#1,}{,\skv@igkeys,}{}{%
+ \skvifcsdefFT{##1/##2/#1.@cbk}{%
+ \skv@err{Key '#1' isn't defined
+ \MessageBreak on path '##1/##2'}\skv@ehd
+ }{%
+ \edef\skv@tempd{%
+ \skvexpandonce\skv@tempd
+ \skvprependkeycode[##1]{##2}{#1}{%
+ \skvletcs\noexpand\reserved@a{##1/##2/#1.@value}%
+ \edef\noexpand#2{%
+ % Don't use \skvcurrentvalue here, since this
+ % changes when .setkeys is nested:
+ \skvexpandonce\skvexpander{\noexpand\reserved@a}%
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+ \dirkeys@pathlist
+}
+
+\skvrobustdef*\dirkeys@keyslet#1{%
+ \def\skv@pathdo##1##2{%
+ \skv@makeprefix{##1}%
+ \skv@makeheader{##2}%
+ \skv@keyslet{#1}%
+ }%
+ \dirkeys@pathlist
+}
% #1: <key-1>=<arg-1>,...,<key-n>=<arg-n>
% #2: <arg.expander.type>
%
\skvrobustdef*\dirkeys@assignarg#1#2{%
\begingroup
- % Don't take #1 inside \skv@doonroot because it contains parameters:
+ % Don't take #1 inside \skv@pathdo because it contains parameter
+ % characters:
\edef\skv@tempd{\unexpanded{#1}}%
\def\skv@tempe{}%
\skvkvnormalize\skv@tempd
- \def\skv@doonroot##1##2{%
+ \def\skv@pathdo##1##2{%
\skvletcs\skv@igkeys{##1/##2/.@ignoredkeys}%
\skvifdefTF\skv@igkeys{}{\def\skv@igkeys{}}%
\skvcommaloop*\skv@tempd\skv@tempa{%
- \skv@kvosplit\skv@tempa{%
+ \skv@okvsplit\skv@tempa{%
\skvxifinTF{,####1,}{,\skv@igkeys,}{}{%
\skvifcsdefTF{##1/##2/####1.@cbk}{%
\skvifblankTF{####2}{}{%
@@ -5685,13 +6793,14 @@
}%
}%
}{%
- \skv@err{Key '####1' is undefined in family '##1/##2'}\@ehd
+ \skv@err{Key '####1' is undefined
+ \MessageBreak in family '##1/##2'}\skv@ehd
}%
}%
}%
}%
}%
- \dirkeys@getcurrentroots\skv@doonroot
+ \dirkeys@pathlist
\expandafter\endgroup\skv@tempe
}
@@ -5710,48 +6819,47 @@
}%
}{%
\skv@err{No default value for key '\skvcurrentkey'
- \MessageBreak in family '#1/#2'}\@ehd
+ \MessageBreak in family '#1/#2'}\skv@ehd
}%
}%
\skvexpanded{\endgroup
\skvsetkeys*+[#1]{#2}{\skvexpandonce\skv@defaultlist}%
}%
}
-
-\skvrobustdef*\dirkeys@dounknownkeyhandler#1{%
+\skvrobustdef*\dirkeys@setunknownkeyhandler#1{%
\begingroup
- \def\skv@tempa{}\def\skv@tempb{}%
- \def\do##1##2{%
- \skvxifinTF{,##1,}{,\skv@tempa,}{}{%
- \edef\skv@tempa{%
+ \edef\skv@tempa{\unexpanded{#1}}%
+ \def\skv@tempb{}%
+ \toks@{##1##2##3##4}%
+ \def\skv@pathdo##1##2{%
+ \skv@makeprefix{##1}%
+ \skv@makeheader{##2}%
+ \edef\skv@tempb{%
+ \skvexpandonce\skv@tempb\protected
+ \skvcsdef{\skvcurrentpath.@famhandler}\the\toks@{%
\skvexpandonce\skv@tempa
- \ifx\skv@tempa\@empty\else,\fi##1%
- }%
- }%
- \skvxifinTF{,##2,}{,\skv@tempb,}{}{%
- \edef\skv@tempb{%
- \skvexpandonce\skv@tempb
- \ifx\skv@tempb\@empty\else,\fi##2%
}%
}%
}%
- \dirkeys@getcurrentroots\do
- \skvexpanded{\endgroup
- \skvunknownkeyhandler\ifskv@handlerswa+\fi[\skv@tempa]{\skv@tempb}%
- }{#1}%
+ \dirkeys@pathlist
+ \expandafter\endgroup\skv@tempb
}
%%++++++++++++++++++++++++++ Try setting keys +++++++++++++++++++++++%%
%
-% \skvtrysetkeys[<options>]{<keyvals>}
-% .try set keys={<options>}
+% \skvtrysetkeys[<paths>]{<keyvals>}
+%
+% \directkeys{
+% .try set keys={<options>}, where
+% <options> includes <paths> and key-value list (see below).
+% }
%
% Try to set a given key-value list on the paths given by the independent
-% options '.prefix/.prefixes' and '.family/.families' of \skvtrysetkeys. If
-% called within \directkeys (via the handler '.try set keys'), \skvtrysetkeys
-% will ignore the paths that are currently prevailing within \directkeys.
-% That is, within \directkeys, the handler '.try set keys' acts independent
-% of local circumstances of \directkeys.
+% <paths> of \skvtrysetkeys. If called within \directkeys (via the handler
+% '.try set keys'), \skvtrysetkeys will ignore the paths that are currently
+% prevailing within \directkeys. That is, within \directkeys, the handler
+% '.try set keys' acts independent of local circumstances of \directkeys
+% and uses its own paths from <options>.
%
% Save the known/found keys in the macro suggested by the option
% <success list macro>. The user can inspect this macro to see the found
@@ -5776,7 +6884,7 @@
% .try:
% The maximum number of the sum of successful and unsuccessful
% attempts that should be made to set a key in the given SFs. The
-% default value of <try> is 12.
+% default value of <try> is 100.
% .upper goal/.max success:
% The max. number of search families (SF) in which a given key should
% be set/executed, if the key existed in those families. The number of
@@ -5785,11 +6893,18 @@
% .lower goal/.min success:
% The min. number of search families (SF) in which a given key should
% be set/executed. For any key, if <hits> is less than <lower goal>
-% an error will be flagged.
-% .prefix/.prefixes:
-% The prefixes in which the keys should be set (default=KV).
-% .families/.family:
-% Families to search.
+% an error will be flagged. The default of this is 0, meaning that
+% by default no error message will be returned if a key isn't found
+% on any of the paths.
+% .path/.paths:
+% Paths to search <pref1>/<fam1>,...,<pref-n>/<fam-n>.
+% .prefix
+% The prefix to search (default: KV). The number of prefixes can't
+% be more than 1. If you have multiple prefixes, then use the
+% .paths key. The given prefix will be prepended to all the given
+% families.
+% .families/.family
+% The families to search <fam1>,...,<fam-n>.
% .ignore keys:
% Ignored keys. These keys will not be set even if they are found.
% .save known keys:
@@ -5797,250 +6912,312 @@
% in a macro.
% .save known keys in/success list macro/success list:
% The macro into which to save known keys. Each known key is
-% saved in the format: <pref>/<fam>/<key>. The user can
+% saved in the format <pref>/<fam>/<key>. The user can
% inspect this macro to see the found keys. The default macro is
% \skvsuccesslist.
-%
-% NOTE:
-%
-% When the paths are many, the user has to be right in choosing the
-% options '.try', '.upper goal' and '.lower goal', otherwise not enough paths
-% will be searched. For example, if you want some 'keya' to be set on
-% paths KV1/fam1, KV1/fam2, KV2/fam1, KV2/fam2, and you set '.try=2' or
-% '.upper goal=2', then only 2 paths will be traversed; not the desired 4.
+% .save unknown keys:
+% The boolean that directs that unknown keys should be saved
+% in a macro.
+% .save unknown keys in/fail list macro/fail list:
+% The macro into which to save unknown keys. Each unknown key is
+% saved in the format <pref>/<fam>/<key>. The user can
+% inspect this macro to see the unknown keys. The default macro is
+% \skvfaillist.
+% .path exception
+% The user-supplied action (code) to take when a key hasn't been found
+% on the curent path of the given paths. The default path exception
+% is nil.
+% .hits exception
+% The user-supplied action (code) to take when the number of hits is
+% less than preferred minimum success. This may specify retrying on
+% some other paths. The default exception is an error message.
+%
+% NOTES:
+%
+% 1. When the paths are many, the user has to be right in choosing the
+% options '.try', '.upper goal' and '.lower goal', otherwise not
+% enough paths will be searched. For example, if you want some 'keya'
+% to be set on paths KV1/fam1, KV1/fam2, KV2/fam1, KV2/fam2, and you
+% set '.try=2' or '.upper goal=2', then only 2 paths will be traversed;
+% not the desired 4.
-\skvrobustdef*\dirkeys@trysetkeys#1{%
- \begingroup
- \@tempcnta\skvz@
- \def\skv@tempc{}%
- \def\skv@tempd{}%
- \def\skv@tempa##1={%
- \begingroup
- \let\bgroup\relax
- \@ifnextchar\skv@orig@bgroup{%
- \endgroup\@tempswatrue\skv@tempb##1=%
- }{%
- \endgroup\@tempswafalse\skv@tempb##1=%
- }%
- }%
- \def\skv@tempb##1=##2=##3\skv@nil{%
- \skvxifinTF{,##1,}{,.key values,.kv,.kv list,}{%
- \advance\@tempcnta\@ne
- \skvifnumTF\@tempcnta>\@ne{%
- \skv@err{Multiple entries for key '.key values' or '.kv'}\@ehd
- }{%
- \edef\skv@tempd{\skvifstrcmpTF{##2}{^skv^}{}{\unexpanded{##2}}}%
- }%
- }{%
- \edef\skv@tempc{%
- \skvexpandonce\skv@tempc\ifx\skv@tempc\@empty\else,\fi
- ##1%
- \skvifstrcmpTF{##2}{^skv^}{}{%
- =\if@tempswa{\fi\unexpanded{##2}\if@tempswa}\fi
- }%
- }%
- }%
- }%
- \skvkvparse{#1}\skv@prova{%
- \expandafter\skv@tempa\skv@prova=^skv^=\skv@nil
- }%
- \ifx\skv@tempd\@empty
- \skv@err{No key-value pairs for handler '.try set keys'}\@ehd
- \fi
- \skvexpanded{\endgroup
- \noexpand\skv@trysetkeys[\skvexpandonce\skv@tempc]%
- {\skvexpandonce\skv@tempd}%
- }%
-}
\skvedefinekeys[SKV]{skvtryset}[skvtry@]{%
- .ord/{.try,.max attempt,.max attempts,.total}/12/
+ .initialize keys after define,
+ .ord/{.try,.max attempt,.max attempts,.total}/100/
+ \skvensureinteger{.max attempt}{#1}%
\def\skvtry@maxattempts{#1}%
\skvstripouterbraces{2}\skvtry@maxattempts
\edef\skvtry@maxattempts{\number\skvtry@maxattempts}%
- \skvensureinteger{.max attempt}\skvtry@maxattempts
\ifnum\skvtry@maxattempts<\@ne
\skv@err{The max. number of attempts ('try')
- \MessageBreak can't be less than 1}\@ehd
+ \MessageBreak can't be less than 1}\skv@ehd
\fi
,
.ord/{.upper goal,.max success,.max hits}/1/
+ \skvensureinteger{upper goal}{#1}%
\def\skvtry@maxsuccess{#1}%
\skvstripouterbraces{2}\skvtry@maxsuccess
\edef\skvtry@maxsuccess{\number\skvtry@maxsuccess}%
- \skvensureinteger{upper goal}\skvtry@maxsuccess
\ifnum\skvtry@maxsuccess<\@ne
\skv@err{The max. number of successful attempts
- \MessageBreak ('upper goal') can't be less than 1}\@ehd
+ \MessageBreak ('upper goal') can't be less than 1}\skv@ehd
\fi
,
- .ord/{.min success,.lower goal,.goal}/1/
+ .ord/{.min success,.lower goal,.goal}/0/
+ \skvensureinteger{lower goal}{#1}%
\def\skvtry@minsuccess{#1}%
\skvstripouterbraces{2}\skvtry@minsuccess
\edef\skvtry@minsuccess{\number\skvtry@minsuccess}%
- \skvensureinteger{lower goal}\skvtry@minsuccess
- \ifnum\skvtry@minsuccess<\@ne
+ \ifnum\skvtry@minsuccess<\skvz@
\skv@err{The min. number of successful attempts
- \MessageBreak ('lower goal') can't be less than 1}\@ehd
+ \MessageBreak ('lower goal') can't be less than 0}\skv@ehd
\fi
,
- .ord/{.prefix,.prefixes,.add prefix,.add prefixes}/\skv@defaultpref/
- \edef\skvtry@prefs{#1}
- \skvstripouterbraces{2}\skvtry@prefs
- \edef\skvtry@prefs{%
- \skvifemptyTF\skvtry@prefs\skv@defaultpref\skvtry@prefs
- }%
- \ifskv@insa
- \skvexpbracenext{\skvmergelist\skvtry@prefs}\dirkeys@prefixlist
- \fi
- \skvcsvnormalize\skvtry@prefs
- ,
- .ord/{.family,.families,.add family,.add families}/\@nil/
- \edef\skvtry@fams{#1}
- \skvstripouterbraces{2}\skvtry@fams
- \ifx\skvtry@fams\@nnil\else
- \skvstripouterbraces{2}\skvtry@fams
+ % #1=<pref1>/<fam1>,...,<pref-n>/<fam-n>
+ .ord/{.path,.paths,.add path,.add paths}/\skv@nil/{
+ \edef\skv@tempa{#1}%
+ \skvstripouterbraces{2}\skv@tempa
+ \ifx\skv@tempa\skv@nnil\def\skv@tempa{}\fi
+ \ifx\skv@tempa\@empty\else
+ \skvcommaparse*\skv@tempa\skv@prova{%
+ \skv@splitpath@a\skv@prova\skv@tempa\skv@tempb
+ \edef\skv@prova{{\skv@tempa}{\skv@tempb}}%
+ \skvxifinTF{\skvoxdetok\skv@prova}{\skvoxdetok\skvtry@pathlist}{}{%
+ \edef\skvtry@pathlist{%
+ \skvexpandonce\skvtry@pathlist\noexpand\skvtry@pathdo\skv@prova
+ }%
+ }%
+ }%
\ifskv@insa
- \skvexpbracenext{\skvmergelist\skvtry@fams}\dirkeys@familylist
+ \begingroup
+ \def\skv@pathdo##1##2{%
+ \edef\skv@prova{\detokenize{{##1}{##2}}}%
+ \skvxifinTF{\skv@prova}{\skvoxdetok\skvtry@pathlist}{}{%
+ \edef\skvtry@pathlist{%
+ \skvexpandonce\skvtry@pathlist
+ \noexpand\skvtry@pathdo{##1}{##2}%
+ }%
+ }%
+ }%
+ \dirkeys@pathlist
+ \skvaftergroupdef\skvtry@pathlist\endgroup
\fi
- \skvcsvnormalize\skvtry@fams
\fi
+ },
+ % Prefix is used in making \skvtry@pathlist in .family:
+ .ord/{.prefix}/\skvdefaultprefix/
+ \skv@ifoneprefix{#1}{%
+ \def\skvtry@pref{#1}
+ \skvstripouterbraces{2}\skvtry@pref
+ }{%
+ \skv@err{Only one prefix is allowed in '.try set keys'}\skv@ehd
+ }
,
- .ord/{.path,.paths,.add path,.add paths,.root,.roots}/\@nil/
- \edef\skv@tempa{\skvtrimspace{#1}}
- \skvstripouterbraces{2}\skv@tempa
- \ifcase0\ifx\skv@tempa\@nnil1\else
- \ifx\skv@tempa\@empty1\fi\fi\relax\skvafterfi
- \skvexpbracenext\skvtry@processpaths\skv@tempa
+ .ord/.prefixes//
+ \ifskvindef\else
+ \skv@err{Key '.prefixes' not defined; try '.paths'}\skv@ehd
\fi
,
- .ord/{.ignore keys,.filter keys}//
- \def\skvtry@igkeys{#1}
- \skvstripouterbraces{2}\skvtry@igkeys
+ .ord/{.family,.families}/\skv@nil/
+ \edef\skvtry@fams{#1}
+ \ifskvindef\else
+ \ifx\skvtry@fams\skv@nnil
+ \skv@err{No family specified for command
+ \MessageBreak\string\skvtrysetkeys or handler '.try set keys'}\skv@ehd
+ \fi
+ \fi
+ \skvstripouterbraces{2}\skvtry@fams
+ \skv@makepaths\skvtry@pref\skvtry@fams\skvtry@pathlist\skvtry@pathdo
,
- .ord/{.save known keys,.save success}/true/
- \def\skvtry@savesuccess{#1}
- \skvstripouterbraces{2}\skvtry@savesuccess
- \edef\skvtry@savesuccess{0\ifx\skvtry@savesuccess\skv@truetoks0\else1\fi}
+ .ord/{.ignore keys}//
+ \def\skvtry@igkeys{#1}
+ \ifx\skvtry@igkeys\@empty\else
+ \skvstripouterbraces{2}\skvtry@igkeys
+ \fi
,
.ord/{.save known keys in,.success list,.success list macro}/
\skvsuccesslist/
- \def\skvtry@successlistmacro{#1}
- \skvstripouterbraces{2}\skvtry@successlistmacro
+ \skviflacus#1\then
+ \def\skvtry@knownkeyslistmacro{\skvsuccesslist}%
+ \else
+ \def\skvtry@knownkeyslistmacro{#1}
+ \fi
+ \skvstripouterbraces{2}\skvtry@knownkeyslistmacro
+ ,
+ .ord/{.save unknown keys in,.fail list,.fail list macro}/
+ \skvfaillist/
+ \skviflacus#1\then
+ \def\skvtry@unknownkeyslistmacro{\skvfaillist}%
+ \else
+ \def\skvtry@unknownkeyslistmacro{#1}
+ \fi
+ \skvstripouterbraces{2}\skvtry@unknownkeyslistmacro
+ ,
+ % Exception on each path, if key isn't found:
+ .ord/{.if any path fails,.if a path fails,.if path fails}//
+ \edef\skvtry@pathexception{\unexpanded{#1}}
+ \skvstripouterbraces{1}\skvtry@pathexception
+ ,
+ % Exception to be triggered after all paths have been searched and the key
+ % isn't found:
+ .ord/{.if hits less than target,.if hits less than goal,
+ .if hits are less than goal}//
+ \edef\skvtry@hitsexception{\unexpanded{#1}}
+ \skvstripouterbraces{1}\skvtry@hitsexception
,
-}
-\skvrobustdef*\skvtry@processpaths#1{%
- \def\skvtry@prefs{}%
- \def\skvtry@fams{}%
- \def\skv@tempc##1/##2/##3\skv@nil{%
- \def\skv@tempa{##1}%
- \def\skv@tempb{##2}%
- \skvstripouterbraces{2}\skv@tempa
- \skvstripouterbraces{2}\skv@tempb
- \edef\skvtry@prefs{%
- \skvtry@prefs\ifx\skvtry@prefs\@empty\else,\fi\skv@tempa
- }%
- \edef\skvtry@fams{%
- \skvtry@fams\ifx\skvtry@fams\@empty\else,\fi\skv@tempb
- }%
- }%
- \skvcommaparse{#1}\skv@prova{%
- \expandafter\skv@tempc\skv@prova//\skv@nil
- }%
- \ifskv@insa
- \skvexpbracenext{\skvmergelist\skvtry@prefs}\dirkeys@prefixlist
- \skvexpbracenext{\skvmergelist\skvtry@fams}\dirkeys@familylist
- \fi
- \skvcsvnormalize\skvtry@prefs
- \skvcsvnormalize\skvtry@fams
-}
-\skvsetkeys[SKV]{skvtryset}{.try,.upper goal,.lower goal,.prefix,
- .family=^skv^,.ignore keys,.save success,.success list macro
}
% \skvtrysetkeys[<options>]{<kvlist>}
\skvrobustdef*\skvtrysetkeys{\skv@testopt\skv@trysetkeys{}}
\skvrobustdef*\skv@trysetkeys[#1]#2{%
\skvpushfunctions\skvtrysetkeys{%
- \do\skvtry@fams\do\skvtry@prefs\do\skvtry@maxattempts
+ \do\skvtry@maxattempts\do\skvtry@hitsexception\do\skvtry@pathexception
\do\skvtry@minsuccess\do\skvtry@maxsuccess\do\skvtry@igkeys
- \do\skvtry@successlistmacro\do\skvtry@savesuccess
- \do\CurrentOption\do\skv@tempsuccesslist
- \do\skvcurrentkey\do\skvcurrentpath
+ \do\skvtry@knownkeyslistmacro\do\skv@tempknownkeys
+ \do\skvtry@unknownkeyslistmacro\do\skv@tempunknownkeys
+ \do\skv@triedlist\do\CurrentOption\do\skvtry@pref\do\skvtry@fams
+ \do\skvtry@pathlist\do\skv@pathdo\do\skvcurrentkey\do\skvcurrentpath
\do\skvcurrentprefix\do\skvcurrentfamily
}\skv@trysetkeysdepth
+ % Initialize \skvtry@pathlist; see the definition of the keys of
+ % \skvtrysetkeys above.
+ \def\skvtry@pathlist{}%
\skvsetkeys[SKV]{skvtryset}{#1}%
- \ifx\skvtry@fams\skv@rej
- \skv@err{No families in which to 'try' to set keys}\@ehd
+ \ifx\skvtry@pathlist\@empty
+ \skv@err{No families in which to 'try' to set keys}\skv@ehd
\fi
- \skv@getkeynames{#2}\skv@naa
- \expandafter\def\skvtry@successlistmacro{}%
- \def\skv@tempsuccesslist{}%
+ % To avoid repeated computation of \skv@currentnames in \skv@setkeys@a
+ % for each key in the next loop:
+ \skv@getnamesofkeys{#2}\skv@currentnames
+ \expandafter\def\skvtry@knownkeyslistmacro{}%
+ \expandafter\def\skvtry@unknownkeyslistmacro{}%
+ \skvemptify{\skv@tempknownkeys,\skv@tempunknownkeys,\skv@triedlist}%
\skv@intrytrue
\skvcommaparse{#2}\CurrentOption{%
- \expandafter\skv@g@tkeyname\CurrentOption=\skv@nil\skvcurrentkey
- \skvxifinTF{,\skvcurrentkey,}{,\skvtry@igkeys,}{}{%
+ \expandafter\skv@g@tkeyname\CurrentOption=\skv@getname@nil\skvcurrentkey
+ \skvifemptyTF\skvtry@igkeys{%
+ \@firstofone
+ }{%
+ \skvxifinTF{,\skvcurrentkey,}{,\skvtry@igkeys,}{}%
+ }{%
+ % \skv@triedlist saves non-ignored list:
+ \edef\skv@triedlist{\skvaddlist,\skv@triedlist\skvcurrentkey}%
\skvpushfunctions\skv@trysetkeys@istate{%
- \do\CurrentOption\do\skvcurrentkey\do\skvcurrentpath
- \do\skvcurrentprefix\do\skvcurrentfamily
- \do\skv@attempts\do\skv@hits\do\skv@breakprefloop
- \do\ifskv@success
- }\skv@trysetkeysdepth@b
+ \do\CurrentOption\do\skvcurrentkey\do\skv@attempts
+ \do\skv@hits\do\skv@failedattempts\do\ifskv@success\do\skvtry@pathdo
+ }\skv@trysetkeysidepth
\skv@successfalse
- % Don't use \chardef here; it won't print in the error message
- % if it wasn't incremented:
- \def\skv@attempts{0}%
- \def\skv@hits{0}%
- \def\skv@breakprefloop{01}%
- \skvcommaloop*\skvtry@prefs\skvcurrentprefix{%
- \skvcommaloop*\skvtry@fams\skvcurrentfamily{%
- \skvexpanded{%
- % Don't use \skv@setkeys@a here: \skv@fams, etc.
- % will be mixed up.
- \skvsetkeys[\skvcurrentprefix]{\skvcurrentfamily}%
- {\skvexpandonce\CurrentOption}%
+ \skvinizero{\skv@attempts,\skv@hits,\skv@failedattempts}%
+ \def\skvtry@pathdo##1##2{%
+ \edef\skv@fams{##2}%
+ \skv@makeprefix{##1}%
+ % \ifskv@st is 'false' because we always save unknown keys while
+ % in .try; and the branch for \ifskv@st is never taken when
+ % in .try (see \skv@setkeys@d).
+ \skv@stfalse\skv@plfalse\skv@viarootofsetkeysfalse
+ \skvexpbracenext{\skv@setkeys@a[]}\CurrentOption
+ \edef\skv@attempts{\the\numexpr\skv@attempts+1}%
+ \ifskv@success
+ \edef\skv@hits{\the\numexpr\skv@hits+1}%
+ \edef\skv@tempknownkeys{%
+ \skvaddlist,\skv@tempknownkeys\skvcurrenttriple
}%
- \edef\skv@attempts{\the\numexpr\skv@attempts+1}%
- \ifskv@success
- \edef\skv@hits{\the\numexpr\skv@hits+1}%
- \if\skvtry@savesuccess
- \edef\skv@tempsuccesslist{%
- \skvaddlist,\skv@tempsuccesslist\skvcurrenttriple
- }%
- \fi
- \fi
- \ifnum\skv@hits<\skvtry@maxsuccess\relax
- \ifnum\skv@attempts<\skvtry@maxattempts\relax\else
- \skvbreakloop
- \def\skv@breakprefloop{00}%
- \fi
- \else
- \skvbreakloop
- \def\skv@breakprefloop{00}%
+ \else
+ % \skv@failedattempts is currently unused.
+ \edef\skv@failedattempts{\the\numexpr\skv@failedattempts+1}%
+ \edef\skv@tempunknownkeys{%
+ \skvaddlist,\skv@tempunknownkeys\skvcurrenttriple
+ }%
+ \expandafter\expandafter\expandafter\skvtry@pathexception
+ \fi
+ \ifnum\skv@hits<\skvtry@maxsuccess\relax
+ \ifnum\skv@attempts<\skvtry@maxattempts\relax\else
+ \let\skvtry@pathdo\@gobbletwo
\fi
- }%
- \if\skv@breakprefloop
- \skvbreakloop
+ \else
+ \let\skvtry@pathdo\@gobbletwo
\fi
}%
+ \skvtry@pathlist
\ifnum\skv@hits<\skvtry@minsuccess\relax
- \skv@err{Success target '\skvtry@minsuccess' wasn't reached
- \MessageBreak for key '\skvcurrentkey' by
- \ifskv@insa'.search also set'\else
- \noexpand\skvtrysetkeys\fi.
- \MessageBreak Actual hits were '\skv@hits'}\@ehd
+ \ifx\skv@triedlist\@empty
+ \skv@err{Empty try list; all keys were probably ignored}\skv@ehd
+ \else
+ \ifx\skvtry@hitsexception\@empty
+ \skv@err{Success target '\skvtry@minsuccess' wasn't reached
+ \MessageBreak for key '\skvcurrentkey' by
+ \ifskv@insa'.search also set'\else
+ '.try set keys' or \noexpand\skvtrysetkeys\fi.
+ \MessageBreak Actual hits were '\skv@hits'}\skv@ehd
+ \else
+ \expandafter\expandafter\expandafter\expandafter\expandafter
+ \expandafter\expandafter\skvtry@hitsexception
+ \fi
+ \fi
\fi
- \skvpopfunctions\skv@trysetkeys@istate\skv@trysetkeysdepth@b
+ \skvpopfunctions\skv@trysetkeys@istate\skv@trysetkeysidepth
}%
}%
- \expandafter\let\skvtry@successlistmacro\skv@tempsuccesslist
+ \ifx\skv@triedlist\@empty
+ \skv@warn{Empty try list in '.try set keys';
+ \MessageBreak all keys were probably ignored}\skv@ehd
+ \fi
+ \expandafter\let\skvtry@knownkeyslistmacro\skv@tempknownkeys
+ \expandafter\let\skvtry@unknownkeyslistmacro\skv@tempunknownkeys
\ifnum\skv@trysetkeysdepth=\@ne
\skv@intryfalse\skv@insafalse
\let\do\skvundef
- \do\skv@breakprefloop\do\skv@attempts\do\skv@hits
- \do\skv@tempsuccesslist
+ \do\skv@triedlist\do\skv@attempts\do\skv@hits\do\skv@failedattempts
+ \do\skv@tempknownkeys\do\skv@tempunknownkeys
\fi
\skvpopfunctions\skvtrysetkeys\skv@trysetkeysdepth
}
+% In \directkeys, \dirkeys@trysetkeys will be called instead of \skvtrysetkeys:
+\skvrobustdef*\dirkeys@trysetkeys#1{%
+ \begingroup
+ \@tempcnta\skvz@
+ \def\skv@tempc{}\def\skv@tempd{}%
+ % Prepare to preserve outer brace in key value:
+ \def\skv@tempa##1={%
+ \begingroup
+ \let\bgroup\relax
+ \@ifnextchar\skv@orig@bgroup{%
+ \endgroup\@tempswatrue\skv@tempb##1=%
+ }{%
+ \endgroup\@tempswafalse\skv@tempb##1=%
+ }%
+ }%
+ % Because of the need to preserve outer braces in key values, don't
+ % use \skv@kvsplit here.
+ \def\skv@tempb##1=##2=##3\skv@nil{%
+ \skvxifinTF{,##1,}{,.key values,.kv,.kv list,}{%
+ \advance\@tempcnta\@ne
+ \skvifnumTF\@tempcnta>\@ne{%
+ \skv@err{Multiple entries for key
+ \MessageBreak '.key values' or '.kv' or '.kv list'}\skv@ehd
+ }{%
+ \edef\skv@tempd{\skvifstrcmpTF{##2}{^skv^}{}{\unexpanded{##2}}}%
+ }%
+ }{%
+ \edef\skv@tempc{%
+ \skvaddlist,\skv@tempc##1%
+ \skvifstrcmpTF{##2}{^skv^}{}{%
+ =\if@tempswa{\fi\unexpanded{##2}\if@tempswa}\fi
+ }%
+ }%
+ }%
+ }%
+ \skvkvparse{#1}\skv@prova{%
+ \expandafter\skv@tempa\skv@prova=^skv^=\skv@nil
+ }%
+ \ifx\skv@tempd\@empty
+ \skv@err{No key-value pairs for handler '.try set keys'}\skv@ehd
+ \fi
+ \skvexpanded{\endgroup
+ \noexpand\skv@trysetkeys[\skvexpandonce\skv@tempc]%
+ {\skvexpandonce\skv@tempd}%
+ }%
+}
%%+++++++++++++++++++++++++ 'search also' set keys +++++++++++++++++++%%
%
@@ -6051,10 +7228,9 @@
% <options>.
%
% 1. The only difference between \skvsasetkeys and \skvtrysetkeys is that,
-% when in \directkeys, the values of the options <prefix/prefixes> and
-% <family/families> of \skvsasetkeys are added to the current
-% active prefixes and families from the lists \dirkeys@prefixlist and
-% \dirkeys@familylist. Outside of \directkeys, the commands
+% when in \directkeys, the values of the option 'paths' of \skvsasetkeys
+% are added to the current active paths from the lists
+% \dirkeys@pathlist. Outside of \directkeys, the commands
% \skvsasetkeys and \skvtrysetkeys are the same.
%
% 2. All the options of \skvtrysetkeys apply to \skvsasetkeys.
@@ -6062,66 +7238,107 @@
\skvnewlet\skvsasetkeys\skvtrysetkeys
\skvrobustdef*\dirkeys@sasetkeys#1{%
\skv@insatrue
- \skvifdefTF\dirkeys@familylist{}{\def\dirkeys@familylist{}}%
- \skvifdefTF\dirkeys@prefixlist{}{\def\dirkeys@prefixlist{}}%
\dirkeys@trysetkeys{#1}%
}
-
-% \dirkeys@addorremoveroots{<list>}{<operator>}
-\skvrobustdef*\dirkeys@addorremoveroots#1#2{%
- \edef\skv@prova{\unexpanded{#1}}%
- \skvcsvnormalize[/]\skv@prova
- \def\skv@tempa{}\def\skv@tempb{}%
- \skvcommaparse*\skv@prova\skv@prova{%
- \skv@trimslashes\skv@prova
- \skvexpbracenext\skv@slsplit\skv@prova{%
- \skvifstrcmpTF{##2}{^skv^}{%
- \let\skv@prova\skv@defaultpref
- \def\skv@provb{##1}%
- }{%
- \def\skv@prova{##1}\def\skv@provb{##2}%
- }%
- \skvxifinTF{,\skv@prova,}{,\skv@tempa,}{}{%
- \edef\skv@tempa{\skv@tempa\ifx\skv@tempa\@empty\else,\fi\skv@prova}%
+% \dirkeys@addpaths{<paths>}
+% Elements of <path> will have the form '{<pref>}/{<fam>}'
+\skvrobustdef*\dirkeys@addpaths#1{%
+ \skv@formatpaths{#1}\dirkeys@pathlist
+}
+% \dirkeys@removepaths{<list>}
+\skvrobustdef*\dirkeys@removepaths#1{%
+ \begingroup
+ \edef\skv@tempa{\unexpanded{#1}}%
+ \skvcsvnormalize[,]\skv@tempa
+ \skvcsvnormalize[/]\skv@tempa
+ \def\skv@tempb{}%
+ \def\skv@pathdo##1##2{%
+ \skvxifinTF{,\detokenize{##1/##2},}{,\skvoxdetok\skv@tempa,}{}{%
+ \edef\skv@tempb{%
+ \skvexpandonce\skv@tempb
+ \noexpand\skv@pathdo{##1}{##2}%
}%
- \skvxifinTF{,\skv@provb,}{,\skv@tempb,}{}{%
- \edef\skv@tempb{\skv@tempb\ifx\skv@tempb\@empty\else,\fi\skv@provb}%
+ }%
+ }%
+ \dirkeys@pathlist
+ \let\dirkeys@pathlist\skv@tempb
+ \skvaftergroupdef\dirkeys@pathlist\endgroup
+}
+% \dirkeys@removefams{<list>}
+\skvrobustdef*\dirkeys@removefams#1{%
+ \begingroup
+ \edef\skv@tempa{\unexpanded{#1}}%
+ \skvcsvnormalize\skv@tempa
+ \def\skv@tempb{}%
+ \def\skv@pathdo##1##2{%
+ \skvxifinTF{,\detokenize{##2},}{,\skvoxdetok\skv@tempa,}{}{%
+ \edef\skv@tempb{%
+ \skvexpandonce\skv@tempb
+ \noexpand\skv@pathdo{##1}{##2}%
}%
}%
}%
- \skv@clfalse
- \skvexpbracenext{#2\dirkeys@prefixlist}\skv@tempa
- \skvexpbracenext{#2\dirkeys@familylist}\skv@tempb
+ \dirkeys@pathlist
+ \let\dirkeys@pathlist\skv@tempb
+ \skvaftergroupdef\dirkeys@pathlist\endgroup
+}
+% \dirkeys@collectpaths{<pref.macro>}{<fam.macro>}{<ig.macro>}
+% Collect current prefixes in <pref.macro>, families in <fam.macro> and
+% ignored keys in <ig.macro>.
+\skvrobustdef*\dirkeys@collectpaths#1#2#3{%
+ \begingroup
+ \skvemptify{#1,#2,#3}%
+ \def\skv@pathdo##1##2{%
+ \skvxifinTF{,##1,}{,#1,}{}{\edef#1{\skvaddlist,#1##1}}%
+ \skvxifinTF{,##2,}{,#2,}{}{\edef#2{\skvaddlist,#2##2}}%
+ \skvletcs\skv@igkeys{##1/##2/.@ignoredkeys}%
+ \skvifdefTF\skv@igkeys{}{\def\skv@igkeys{}}%
+ \edef#3{\skvaddlist,#3\skv@igkeys}%
+ }%
+ \dirkeys@pathlist
+ \let\do\skvcmdexit
+ \skvexpanded{\endgroup\do#1\do#2\do#3}%
}
+% Remove leading and trailing slashes in #1.
\skvrobustdef*\skv@trimslashes#1{%
\begingroup
- \skvxifinFT{\skvrelax/}{\skvrelax#1}{}{%
- \def\do/##1\skv@nil{\def#1{##1}}%
- \expandafter\do#1\skv@nil
+ \def\skv@tempa{%
+ \skvxifinFT{\skvrelax/}{\skvrelax#1}{}{%
+ \def\do/##1\skv@nil{\def#1{##1}}%
+ \expandafter\do#1\skv@nil
+ \skv@tempa
+ }%
}%
- \skvxifinFT{/\skvrelax}{#1\skvrelax}{}{%
- \def\do##1/\skv@nil{\def#1{##1}}%
- \expandafter\do#1\skv@nil
+ \skv@tempa
+ \def\skv@tempa{%
+ \skvxifinFT{/\skvrelax}{#1\skvrelax}{}{%
+ \def\do##1/\skv@nil{\def#1{##1}}%
+ \expandafter\do#1\skv@nil
+ \skv@tempa
+ }%
}%
+ \skv@tempa
\skvaftergroupdef#1\endgroup
}
-% \dirkeys@addtocodeorvalue{app/pre}{cbk/value}{<list>}
+% \dirkeys@addtocodeorvalue{app.or.pre}{cbk.or.value}{<list>}
+% <list> has the form <key1>={<value1>},...,<key-n>={<value-n>}
\skvrobustdef*\dirkeys@addtocodeorvalue#1#2#3{%
\begingroup
- % Hid the list from the parameters of \do:
+ % Hid the list from the parameters of \skv@pathdo:
\edef\skv@tempa{\unexpanded{#3}}%
\def\skv@tempb{}%
% ##1=prefix, ##2=family
- \def\do##1##2{%
+ \def\skv@pathdo##1##2{%
\skvletcs\skv@igkeys{##1/##2/.@ignoredkeys}%
\skvifdefTF\skv@igkeys{}{\def\skv@igkeys{}}%
\skvkvparse*\skv@tempa\skv@tempa{%
- \expandafter\skv@kvsplit\expandafter{\skv@tempa}{%
+ \skv@okvsplit\skv@tempa{%
\skvxifinTF{,\detokenize{####1},}{,\skvoxdetok\skv@igkeys,}{}{%
\skvletcs\skv@prova{##1/##2/####1.@#2}%
\skvifdefFT\skv@prova{%
- \skv@err{Key '####1' isn't in family '##1/##2'}\@ehd
+ \skv@err{Key '####1' isn't in family
+ \MessageBreak '##1/##2'}\skv@ehd
}{%
\skvcsedef{##1/##2/####1.@#2}{%
\skvifstrcmpTF{#1}{pre}{%
@@ -6140,7 +7357,7 @@
}%
}%
}%
- \dirkeys@getcurrentroots\do
+ \dirkeys@pathlist
\skvexpanded{\endgroup\skv@tempb}%
}
@@ -6151,7 +7368,7 @@
\edef\skv@tempa{\unexpanded{#1}}%
\def\skv@tempb{}%
% ##1=prefix, ##2=family
- \def\do##1##2{%
+ \def\skv@pathdo##1##2{%
\skvletcs\skv@igkeys{##1/##2/.@ignoredkeys}%
\skvifdefTF\skv@igkeys{}{\def\skv@igkeys{}}%
\skvkvparse*\skv@tempa\skv@tempa{%
@@ -6167,13 +7384,13 @@
\noexpand\skvcsexit{##1/##2/####1.@defa}%
}%
}{%
- \skv@err{Key '####1' is not in family '##1/##2'}\@ehd
+ \skv@err{Key '####1' is not in family '##1/##2'}\skv@ehd
}%
}%
}%
}%
}%
- \dirkeys@getcurrentroots\do
+ \dirkeys@pathlist
\skvexpanded{\endgroup\skv@tempb}%
}
@@ -6184,7 +7401,7 @@
\edef\skv@tempa{\unexpanded{#1}}%
\def\skv@tempb{}%
% ##1=prefix, ##2=family
- \def\do##1##2{%
+ \def\skv@pathdo##1##2{%
\skvletcs\skv@igkeys{##1/##2/.@ignoredkeys}%
\skvifdefTF\skv@igkeys{}{\def\skv@igkeys{}}%
\skvkvparse*\skv@tempa\skv@tempa{%
@@ -6197,38 +7414,47 @@
\noexpand\skvcsexit{##1/##2/####1.@value}%
}%
}{%
- \skv@err{Key '####1' isn't in family '##1/##2'}\@ehd
+ \skv@err{Key '####1' isn't in family '##1/##2'}\skv@ehd
}%
}%
}%
}%
}%
- \dirkeys@getcurrentroots\do
+ \dirkeys@pathlist
\skvexpanded{\endgroup\skv@tempb}%
}
-% \dirkeys@inherit{value.or.cbk.or.defa}{<list>}
-\skvrobustdef*\dirkeys@inherit#1#2{%
+% \dirkeys@inheritproperty{value.or.cbk.or.defa}{<list>}
+\skvrobustdef*\dirkeys@inheritproperty#1#2{%
+ \begingroup
+ \def\skv@tempb{}%
% Hid the list from the parameters of \do:
\edef\skv@tempa{\unexpanded{#2}}%
% ##1=prefix, ##2=family
- \def\do##1##2{%
+ \def\skv@pathdo##1##2{%
\skvletcs\skv@igkeys{##1/##2/.@ignoredkeys}%
\skvifdefTF\skv@igkeys{}{\def\skv@igkeys{}}%
\skvkvparse*\skv@tempa\skv@tempa{%
- \expandafter\skv@slsplit\expandafter{\skv@tempa}{%
+ \skv@oslashsplit\skv@tempa{%
+ % \skv@oslashsplit may return ^skv^ for ####1 or ####2, but
+ % this doesn't matter here, since they will show that the keys
+ % aren't defined.
\skvxifinTF{,\detokenize{####1},}{,\skvoxdetok\skv@igkeys,}{}{%
\ifcase\skvifcsdefTF{##1/##2/####1.@cbk}{0}{1}%
\skvifcsdefTF{##1/##2/####2.@cbk}{0}{1}\relax
- \skvcsletcs{##1/##2/####1.@#1}{##1/##2/####2.@#1}%
+ \edef\skv@tempb{%
+ \skvexpandonce\skv@tempb
+ \skvcsletcs{##1/##2/####1.@#1}{##1/##2/####2.@#1}%
+ }%
\else
- \skv@err{Key '####1' or '####2' isn't in family '##1/##2'}\@ehd
+ \skv@err{Key '####1' or '####2' isn't in family '##1/##2'}\skv@ehd
\fi
}%
}%
}%
}%
- \dirkeys@getcurrentroots\do
+ \dirkeys@pathlist
+ \expandafter\endgroup\skv@tempb
}
% \dirkeys@setbooleanhandler{<handler>}{<boolean>}{<bool.value>}
@@ -6241,17 +7467,17 @@
\csname#2#3\endcsname
}{%
\skv@err{Invalid value '\detokenize{#3}' for handler '#1':
- \MessageBreak its expects either 'true' or 'false'}\@ehd
+ \MessageBreak its expects either 'true' or 'false'}\skv@ehd
}%
}%
}{%
- \skv@err{No boolean '\detokenize{#2}'}\@ehd
+ \skv@err{No boolean '\detokenize{#2}'}\skv@ehd
}%
}
\skvrobustdef*\skv@ensurehandlerdot#1{%
\if.\skv@car@detok#1x\car@nil\else
- \skv@err{A dot (.) must lead handler name '#1'}\@ehd
+ \skv@err{A dot (.) must lead handler name '#1'}\skv@ehd
\fi
}
\skvrobustdef*\dirkeys@handlerloop#1{%
@@ -6259,478 +7485,745 @@
\skvstripouterbraces{2}\skv@tempa
\skvkvparse*\skv@tempa
}
-
+\skvnewdef*\dirkeys@reservedhandlers{}
+\skvrobustdef*\skv@reservedhandlererr{%
+ \skv@err{Handler '##1' is reserved.
+ \MessageBreak Reserved handlers can't be redefined whatsoever}\skv@ehd
+}
+\skvrobustdef*\dirkeys@defhandlers@aux#1{%
+ \skvxifinTF{,#1,}{,\dirkeys@reservedhandlers,}{%
+ \skv@reservedhandlererr
+ }{%
+ \ifskv@inreservedhandler
+ \edef\dirkeys@reservedhandlers{%
+ \dirkeys@reservedhandlers
+ \ifx\dirkeys@reservedhandlers\@empty\else,\fi#1%
+ }%
+ \fi
+ \edef\skv@collection{%
+ \skvexpandonce\skv@collection
+ \protected\skvcsdef{dirkeys@handler@#1}\skvxonce\skv@param{%
+ % We can call \skvcurrenthandler in \skv@body, but when the
+ % handler is cast into another handler, the inheriting handler
+ % will not be the one in \skvcurrenthandler.
+ \def\noexpand\skvcurrenthandler{#1}%
+ \skvexpandonce\skv@body
+ }%
+ }%
+ }%
+}
% \dirkeys@defhandlers{<flag>}{<list>}
+%
% <flag> indicates if we're in <new> (01) or <define> (00) handler.
+%
\skvrobustdef*\dirkeys@defhandlers#1#2{%
- \dirkeys@handlerloop{#2}\skv@tempa{%
- \skv@kvosplit\skv@tempa{%
- \skv@ensurehandlerdot{##1}%
- \skvifplaswTF{#1}{%
- \skvcsdef{dirkeys@handler@##1}####1{##2}%
+ \begingroup
+ \def\skv@collection{}%
+ \def\skv@param{####1\skvhandlereov}%
+ \def\skv@defhandlers@do##1{%
+ \skv@ensurehandlerdot{##1}%
+ \skvifplaswTF{#1}{%
+ \dirkeys@defhandlers@aux{##1}%
+ }{%
+ \skvifcsdefTF{dirkeys@handler@##1}{%
+ \skv@err{Handler '##1' arealdy exists}\skv@ehd
}{%
- \skvifcsdefTF{dirkeys@handler@##1}{%
- \skv@err{Handler '##1' arealdy exists}\@ehd
- }{%
- \skvcsdef{dirkeys@handler@##1}####1\handlereov{##2}%
- }%
+ \dirkeys@defhandlers@aux{##1}%
}%
}%
}%
+ \dirkeys@handlerloop{#2}\skv@prova{%
+ \skv@okvsplit\skv@prova{%
+ % Hide the parameter characters in body:
+ \edef\skv@prova{\unexpanded{##1}}%
+ \skvstripouterbraces{2}\skv@prova
+ \edef\skv@body{\unexpanded{##2}}%
+ \skvcommaparse*\skv@prova\skv@prova{%
+ \expandafter\skv@defhandlers@do\expandafter{\skv@prova}%
+ }%
+ }%
+ }%
+ \skvexpanded{\endgroup
+ \skvexpandonce\skv@collection
+ \skvcmdexit\dirkeys@reservedhandlers
+ }%
}
-
+% \dirkeys@defnarghandlers{<flag>}{<list>}
+%
% Define handlers of more than one argument. This is slightly more
% expensive than '.new handlers':
-% \dirkeys@defnarghandlers{<flag>}{<list>}
-% <flag> indicates if we're in <new> (01) or <define> (00) handler.
+%
+% <flag> indicates whether we're in <new> (01) or <define> (00) handler.
+%
\skvrobustdef*\dirkeys@defnarghandlers#1#2{%
- \dirkeys@handlerloop{#2}\skv@tempa{%
- \skv@kvosplit\skv@tempa{%
- \skv@ensurehandlerdot{##1}%
- \def\skv@tempa####1####2\handler@nil{%
- % ####2 must be hidden in a macro for later use in defining the
- % handler:
- \edef\skv@prova{\unexpanded{####2}}%
- \edef\skv@tempa{\skvgenerateparameters{1}{####1}\handlereov}%
- \def\skv@provb{%
- \edef\skv@tempb{\protected\def\skvnoexpandcs{dirkeys@handler@##1}}%
- \expandafter\expandafter\expandafter\skv@tempb\expandafter
- \skv@tempa\expandafter{\skv@prova}%
- }%
- \skvifplaswTF{#1}{%
- \skv@provb
+ \begingroup
+ \def\skv@collection{}%
+ \def\skv@defhandlers@do##1{%
+ \skv@ensurehandlerdot{##1}%
+ \def\skv@prova####1####2\handler@nil{%
+ \edef\skv@param{\skvgenerateparameters{1}{####1}\skvhandlereov}%
+ \edef\skv@body{\unexpanded{####2}}%
+ \skvifplaswTF{#1}{%
+ \dirkeys@defhandlers@aux{##1}%
+ }{%
+ \skvifcsdefTF{dirkeys@handler@##1}{%
+ \skv@err{Handler '##1' arealdy exists}\skv@ehd
}{%
- \skvifcsdefTF{dirkeys@handler@##1}{%
- \skv@err{Handler '##1' arealdy exists}\@ehd
- }{%
- \skv@provb
- }%
+ \dirkeys@defhandlers@aux{##1}%
}%
}%
- \skv@tempa##2\handler@nil
+ }%
+ \expandafter\skv@prova\skv@provb\handler@nil
+ }%
+ \dirkeys@handlerloop{#2}\skv@prova{%
+ \skv@okvsplit\skv@prova{%
+ \edef\skv@prova{\unexpanded{##1}}%
+ \skvstripouterbraces{2}\skv@prova
+ % Here \skv@body is in \skv@defhandlers@do.
+ \edef\skv@provb{\unexpanded{##2}}%
+ \skvcommaparse*\skv@prova\skv@prova{%
+ \expandafter\skv@defhandlers@do\expandafter{\skv@prova}%
+ }%
}%
}%
+ \skvexpanded{\endgroup
+ \skvexpandonce\skv@collection
+ \skvcmdexit\dirkeys@reservedhandlers
+ }%
}
-
% \dirkeys@handlerlet{<flag>}{<kvlist>}
-% <flag> is either 00 (for define) or 01 (for new handler).
+%
+% 1. <flag> is either 00 (for define) or 01 (for new handler).
+% 2. <kvlist> has the form
+%
+% {<child handler list>}={<parent handler>}
+%
\skvrobustdef*\dirkeys@handlerlet#1#2{%
- \dirkeys@handlerloop{#2}\skv@tempa{%
- \skv@kvosplit\skv@tempa{%
- \skvifcsdefFT{dirkeys@handler@##2}{%
- \skv@err{Handler '##2' doesn't exist}\@ehd
+ \begingroup
+ \def\skv@collection{}%
+ \def\skv@handlerlet@do##1##2{%
+ \skvifblankTF{##1}{}{%
+ \skvxifinTF{,##1,}{,\dirkeys@reservedhandlers,}{%
+ \skv@reservedhandlererr
}{%
- \skvifblankTF{##1}{%
- \skv@err{No child handler}\@ehd
- }{%
- \skvifplaswTF{#1}{}{%
- \skvifcsdefFT{dirkeys@handler@##1}{}{%
- \skv@err{Handler '##1' arealdy exists}\@ehd
- }%
+ \ifskv@inreservedhandler
+ \edef\dirkeys@reservedhandlers{%
+ \dirkeys@reservedhandlers
+ \ifx\dirkeys@reservedhandlers\@empty\else,\fi##1%
}%
+ \fi
+ \skvifplaswTF{#1}{}{%
+ \skvifnamedefFT{dirkeys@handler@##1}{}{%
+ \skv@err{Handler '##1' arealdy exists}\skv@ehd
+ }%
+ }%
+ \edef\skv@collection{%
+ \skvexpandonce\skv@collection
\skvcsletcs{dirkeys@handler@##1}{dirkeys@handler@##2}%
}%
}%
}%
}%
+ \dirkeys@handlerloop{#2}\skv@tempa{%
+ \skv@okvsplit\skv@tempa{%
+ \skvifnamedefTF{dirkeys@handler@##2}{%
+ \skvcommaparse{##1}\skv@prova{%
+ \skvexpbracenext\skv@handlerlet@do\skv@prova{##2}%
+ }%
+ }{%
+ \skv@err{Handler '##2' doesn't exist}\skv@ehd
+ }%
+ }%
+ }%
+ \expandafter\endgroup\skv@collection
}
\skvrobustdef*\skvusehandler#1#2{%
\skv@ensurehandlerdot{#1}%
- \skvifcsdefTF{dirkeys@handler@#1}{%
- \csname dirkeys@handler@#1\endcsname#2\handlereov
+ \skvifnamedefTF{dirkeys@handler@#1}{%
+ \csname dirkeys@handler@#1\endcsname#2\skvhandlereov
}{%
- \skv@err{Handler '#1' is undefined}\@ehd
+ \skv@err{Handler '#1' is undefined}\skv@ehd
}%
}
% The macro that contains the default command in which unknown keys
-% will be saved by some handlers of \dirkeys:
+% will be saved by some handlers of \directkeys:
\skvnewdef*\dirkeys@unknownkeysmacro{\skvfaillist}
% Notes:
-% 1. '.new handlers' must be defined outsied \dirkeys, since it is
-% the one that defines every other handler.
+% 1. '.new reserved handlers' must be defined outsied \directkeys,
+% since we have used it here to defines every other handler.
% 2. It defines definable handlers of one or more arguments. See also
-% '.define handlers' later on (within the next call of \dirkeys).
-\skvrobustcsdef*{dirkeys@handler@.new handlers}#1\handlereov{%
+% '.define handlers' later on (within the next call of \directkeys).
+%
+\skvrobustcsdef*{dirkeys@handler@.new reserved handlers}#1\skvhandlereov{%
+ \skv@inreservedhandlertrue
\dirkeys@defhandlers{01}{#1}%
-}
-
-\dirkeys*{%
- .new handlers={%
- .exec code=#1,
- .define handlers=\dirkeys@defhandlers{00}{#1},
- .define narg handlers=\dirkeys@defnarghandlers{00}{#1},
- .new narg handlers=\dirkeys@defnarghandlers{01}{#1},
- .kill handlers={%
- \dirkeys@handlerloop{#1}\skv@tempa{%
- \skvifcsdefTF{dirkeys@handler@\skv@tempa}{%
- \skvcsundef{dirkeys@handler@\skv@tempa}%
- }{%
- \skv@err{Handler '\skv@tempa' is undefined}\@ehd
- }%
- }%
+ \skv@inreservedhandlerfalse
+}
+\directkeys*{%
+ % Defining new handlers that can't be overloaded:
+ .new reserved handlers={
+ % '.new reserved handlers' and '.define reserved handlers' are the
+ % same thing since reserved handlers can't be overridden or overloaded.
+ {.new reserved handler,.define reserved handlers,
+ .define reserved handler}={
+ \skvusehandler{.new reserved handlers}{#1}
+ },
+ {.exec,.exec code}={#1},
+ {.define handler,.define handlers}={
+ \dirkeys@defhandlers{00}{#1}
+ },
+ {.new handler,.new handlers}={
+ \dirkeys@defhandlers{01}{#1}
+ },
+ {.define narg handler,.define narg handlers}={
+ \dirkeys@defnarghandlers{00}{#1}
+ },
+ {.new narg handler,.new narg handlers}={
+ \dirkeys@defnarghandlers{01}{#1}
+ },
+ % See comment above about '.new reserved handlers':
+ {.new reserved narg handler,.new reserved narg handlers,
+ .define reserved narg handler,.define reserved narg handlers}={
+ \skv@inreservedhandlertrue
+ \dirkeys@defnarghandlers{01}{#1}
+ \skv@inreservedhandlerfalse
+ },
+ {.reserve handlers,.reserve handler}={
+ \edef\skv@prova{\unexpanded{#1}}%
+ \skvstripouterbraces{2}\skv@prova
+ \skvcsvnormalize\skv@prova
+ \edef\dirkeys@reservedhandlers{
+ \dirkeys@reservedhandlers
+ \ifx\dirkeys@reservedhandlers\@empty\else,\fi\skv@prova
+ }
+ },
+ {.kill handler,.kill handlers}={
+ \dirkeys@handlerloop{#1}\skv@tempa{
+ \skvifcsdefTF{dirkeys@handler@\skv@tempa}{
+ \skvcsundef{dirkeys@handler@\skv@tempa}
+ }{
+ \skv@err{Handler '\skv@tempa' is undefined}\skv@ehd
+ }
+ }
},
.use handler=\skvusehandler{#1},
- .handler let*=\dirkeys@handlerlet{00}{#1},
- .handler let=\dirkeys@handlerlet{01}{#1},
- .prefixes={%
- \def\dirkeys@prefixlist{}%
- \skvusehandler{.add prefixes}{#1}%
- },
- .default prefix={%
- \skvdefaultprefix{#1}
- },
- .add prefixes={%
- \skv@clfalse\skv@mergelist\dirkeys@prefixlist{#1}%
- },
- .families={%
- \def\dirkeys@familylist{}%
- \skvusehandler{.add families}{#1}%
- },
- .add families={%
- \skv@clfalse\skv@mergelist\dirkeys@familylist{#1}%
- },
- .roots={%
- \def\dirkeys@prefixlist{}%
- \def\dirkeys@familylist{}%
- \skvusehandler{.add roots}{#1}%
- },
- .add roots={%
- \dirkeys@addorremoveroots{#1}\skvmergelist
- },
- .ignore roots={%
- \dirkeys@addorremoveroots{#1}\skvremoveelements
- },
- .restore roots={%
- \skvusehandler{.add roots}{#1}%
- },
- .ignore prefixes=\skvremoveelements\dirkeys@prefixlist{#1},
- .restore prefixes=\skvmergelist\dirkeys@prefixlist{#1},
- .ignore families=\skvremoveelements\dirkeys@familylist{#1},
- .restore families=\skvmergelist\dirkeys@familylist{#1},
- .ignore keys={%
- \def\skv@doonroot##1##2{%
- \expandafter\skvmergelist
- \csname##1/##2/.@ignoredkeys\endcsname{#1}%
- }%
- \dirkeys@getcurrentroots\skv@doonroot
+ % Allow override:
+ {.handler let*,.handlers let*,.let handler*,.let handlers*,
+ .force handler let}={
+ \dirkeys@handlerlet{00}{#1}
+ },
+ % Disallow override:
+ {.handler let,.handlers let,.let handler,.let handlers}={
+ \dirkeys@handlerlet{01}{#1}
+ },
+ % Let and reserved handlers:
+ {.handler let reserved,.handlers let reserved}={
+ \skv@inreservedhandlertrue
+ \dirkeys@handlerlet{01}{#1}
+ \skv@inreservedhandlerfalse
+ },
+ {.paths,.path,.change path,.change paths,.cd}={
+ \def\dirkeys@pathlist{}\dirkeys@addpaths{#1}
+ },
+ {.add path,.add paths}={
+ \dirkeys@addpaths{#1}
+ },
+ {.ignore path,.ignore paths}={
+ \dirkeys@removepaths{#1}
+ },
+ {.restore path,.restore paths}={
+ \dirkeys@addpaths{#1}
},
- .restore keys={%
- \def\skv@doonroot##1##2{%
+ % Prefix is used in building \dirkeys@pathlist in '.family' handler.
+ % There must be only one current prefix. Use .path to submit multiple
+ % prefixes and families.
+ {.prefix,.change prefix}={
+ \skv@ifoneprefix{#1}{
+ \edef\dirkeys@pref{#1}
+ \skvstripouterbraces{2}\dirkeys@pref
+ }{
+ \skv@err{List of prefixes isn't allowed for handler
+ \MessageBreak '.prefix' in \string\directkeys. You can use
+ \MessageBreak '.paths' to submit multiple prefixes and
+ \MessageBreak families}\skv@ehd
+ }
+ },
+ % Since there can be only one prefix, you couldn't ignore it.
+ {.prefixes,.change prefixes,.ignore prefix,.ignore prefixes}={
+ \skv@err{No handler '\skvcurrenthandler'}\skv@ehd
+ },
+ % See .change path for .cd:
+ {.families,.family,.change family,.change families,.cf}={
+ \edef\dirkeys@fams{#1}
+ \skvstripouterbraces{2}\dirkeys@fams
+ \def\dirkeys@pathlist{}%
+ \skv@makepaths\dirkeys@pref\dirkeys@fams\dirkeys@pathlist\skv@pathdo
+ },
+ {.add family,.add families}={
+ \edef\dirkeys@fams{#1}
+ \skvstripouterbraces{2}\dirkeys@fams
+ \skv@makepaths\dirkeys@pref\dirkeys@fams\dirkeys@pathlist\skv@pathdo
+ },
+ {.ignore family,.ignore families}={
+ \dirkeys@removefams{#1}
+ },
+ {.restore family,.restore families}={
+ \skvusehandler{.add family}{#1}
+ },
+ {.ignore key,.ignore keys}={
+ \skv@pushpathdo
+ \def\skv@pathdo##1##2{
+ \expandafter\skvmergelist\csname##1/##2/.@ignoredkeys\endcsname{#1}
+ }
+ \dirkeys@pathlist
+ \skv@poppathdo
+ },
+ {.restore key,.restore keys}={
+ \skv@pushpathdo
+ \def\skv@pathdo##1##2{
\expandafter\skvremoveelements
- \csname##1/##2/.@ignoredkeys\endcsname{#1}%
- }%
- \dirkeys@getcurrentroots\skv@doonroot
- },
- .holder prefix=\def\dirkeys@holderprefixtoks{#1},
- .push prefixes=\dirkeys@pushmeta{prefix},
- .pop prefixes=\dirkeys@popmeta{prefix},
- .push families=\dirkeys@pushmeta{family},
- .pop families=\dirkeys@popmeta{family},
- .push paths=\dirkeys@pushmeta{prefix}\dirkeys@pushmeta{family},
- .pop paths=\dirkeys@popmeta{prefix}\dirkeys@popmeta{family},
- .push holder prefix=\dirkeys@pushmeta{hp},
- .pop holder prefix=\dirkeys@popmeta{hp},
- .save unknown keys={%
+ \csname##1/##2/.@ignoredkeys\endcsname{#1}
+ }
+ \dirkeys@pathlist
+ \skv@poppathdo
+ },
+ {.holder prefix,.hp}={
+ \def\dirkeys@holderprefixtoks{#1}
+ },
+ % There is no need pushing prefix or family, since they're made
+ % into paths by their key callbacks.
+ {.push path,.push paths}={
+ \dirkeys@pushmeta{path}
+ },
+ {.pop path,.pop paths}={
+ \dirkeys@popmeta{path}
+ },
+ {.push holder prefix,.push hp}={
+ \dirkeys@pushmeta{hp}
+ },
+ {.pop holder prefix,.pop hp}={
+ \dirkeys@popmeta{hp}
+ },
+ .save unknown keys={
\dirkeys@setbooleanhandler
- {.save unknown keys}{dirkeys@saveunknownkeys}{#1}%
+ {.save unknown keys}{dirkeys@saveunknownkeys}{#1}
},
- .save unknown keys in={%
- \skvifblankTF{#1}{}{%
- \skvifescapedTF{#1}{%
+ .save unknown keys in={
+ \skvifblankTF{#1}{%
+ \skv@err{Empty value for handler '.save unknown keys in'}\skv@ehd
+ }{
+ \skvifescapedTF{#1}{
\dirkeys@saveunknownkeystrue
- \def\dirkeys@unknownkeysmacro{#1}%
- }{%
- \skv@err{Token '\detokenize{#1}' is not escaped}\@ehd
- }%
- }%
+ \def\dirkeys@unknownkeysmacro{#1}
+ }{
+ \skv@err{Token '\detokenize{#1}' is not escaped}\skv@ehd
+ }
+ }
},
- .define keys=\skv@handlerswafalse\dirkeys@dodefinekeys{#1},
- .new keys=\skv@handlerswatrue\dirkeys@dodefinekeys{#1},
- .initialize keys after define={%
- \skvusehandler{.set boolean handler}{%
- {.initialize keys after define}{skvdfk@initialize}{#1}%
- }%
+ {.define key,.define keys}={
+ \dirkeys@dodefinekeys{}{#1}
+ },
+ {.new key,.new keys}={
+ \dirkeys@dodefinekeys{*}{#1}
+ },
+ {.define ordinary key,.define ordinary keys,.define ord keys}={
+ \dirkeys@definetypekeys{ord}{}{#1}
+ },
+ {.new ordinary key,.new ordinary keys,.new ord keys}={
+ \dirkeys@definetypekeys{ord}{*}{#1}
+ },
+ {.define command key,.define command keys,.define cmd keys}={
+ \dirkeys@definetypekeys{cmd}{}{#1}
+ },
+ {.new command key,.new command keys,.new cmd keys}={
+ \dirkeys@definetypekeys{cmd}{*}{#1}
+ },
+ {.define boolean key,.define boolean keys,.define bool keys}={
+ \dirkeys@definetypekeys{bool}{}{#1}
+ },
+ {.new boolean key,.new boolean keys,.new bool keys}={
+ \dirkeys@definetypekeys{bool}{*}{#1}
+ },
+ {.define toggle key,.define toggle keys,.define tog keys}={
+ \dirkeys@definetypekeys{bool}{}{#1}
+ },
+ {.new toggle key,.new toggle keys,.new tog keys}={
+ \dirkeys@definetypekeys{bool}{*}{#1}
+ },
+ {.define choice key,.define choice keys}={
+ \dirkeys@definetypekeys{choice}{}{#1}
+ },
+ {.new choice key,.new choice keys}={
+ \dirkeys@definetypekeys{choice}{*}{#1}
},
- .save initial values of keys={%
+ {.initialize keys after define,.initialize after define}={
\dirkeys@setbooleanhandler
- {.save initial values of keys}{skvdfk@saveinitialvalues}{#1}%
+ {.initialize keys after define}{skvdfk@initialize}{#1}
},
- .set keys={%
- \skv@handlerswafalse\skv@handlerswbfalse
- \dirkeys@dosetkeys{#1}\skvsetkeys
+ {.save initial values of keys,.save initial values}={
+ \dirkeys@setbooleanhandler
+ {.save initial values of keys}{skvdfk@saveinitialvalues}{#1}
},
- .set keys*={%
- \skv@handlerswatrue\skv@handlerswbfalse
- \dirkeys@dosetkeys{#1}\skvsetkeys
+ {.set keys,.setkeys,.set}={
+ \dirkeys@setkeys{}{}\skvsetkeys{#1}
},
- .set rmkeys={%
- \skvifblankTF{#1}{%
- \skv@handlerswafalse\skv@handlerswbtrue
- \dirkeys@dosetkeys{}\skvsetrmkeys
- }{%
+ {.set keys*,.setkeys*,.set*,.setkeys save unknown,
+ .set keys save unknown}={
+ \dirkeys@setkeys{*}{}\skvsetkeys{#1}
+ },
+ {.set rmkeys,.setrmkeys,.set remaining keys}={
+ \skvifblankTF{#1}{
+ \dirkeys@setkeys{}{rm}\skvsetrmkeys{}
+ }{
\skv@err{Key 'set rmkeys' can't have value:
\MessageBreak Instead use the key 'ignore keys'
\MessageBreak to suggest keys to be ignored
- \MessageBreak when setting 'rmkeys'}\@ehd
- }%
+ \MessageBreak when setting 'rmkeys'}\skv@ehd
+ }
},
- .set rmkeys*={%
- \skvifblankTF{#1}{%
- \skv@handlerswatrue\skv@handlerswbtrue
- \dirkeys@dosetkeys{}\skvsetrmkeys
- }{%
+ {.set rmkeys*,.setrmkeys*,.set remaining keys*}={
+ \skvifblankTF{#1}{
+ \dirkeys@setkeys{*}{rm}\skvsetrmkeys{}
+ }{
\skv@err{Key 'set rmkeys*' can't have value:
- \MessageBreak Instead use the key 'ignore keys' to suggest keys
- \MessageBreak to be ignored when setting rmkeys}\@ehd
- }%
+ \MessageBreak Instead use the handler '.ignore keys' to suggest keys
+ \MessageBreak to be ignored when setting rmkeys}\skv@ehd
+ }
+ },
+ % '.try set keys' doesn't use the active prefixes and families within
+ % \directkeys. The prefix, families and other options are to be supplied
+ % in the argument #1. The key .key values (or .kv) is used to
+ % supply the key-value pairs.
+ % .try set keys={<options>}
+ {.try set keys,.try set,.try}={
+ \dirkeys@trysetkeys{#1}
+ },
+ % 'search also' set keys.
+ % .sa set keys={<options>}
+ {.search also set keys,.sa set keys}={
+ \dirkeys@sasetkeys{#1}
+ },
+ {.presetkeys,.preset keys}={
+ \dirkeys@dolistedkeys@a{#1}\skv@presetkeys
+ },
+ .gpreset keys={
+ \dirkeys@dolistedkeys@a{#1}\skv@gpresetkeys
+ },
+ .remove preset keys={
+ \dirkeys@dolistedkeys@a{#1}\skvremovepresetkeys
+ },
+ .gremove preset keys={
+ \dirkeys@dolistedkeys@a{#1}\skvgremovepresetkeys
+ },
+ .undefine preset keys={
+ \skv@clfalse\dirkeys@dolistedkeys@b\skv@undefpresetkeys
+ },
+ .gundefine preset keys={
+ \skv@cltrue\dirkeys@dolistedkeys@b\skv@undefpresetkeys
+ },
+ {.postsetkeys,.postset keys}={
+ \dirkeys@dolistedkeys@a{#1}\skv@postsetkeys
+ },
+ .gpostset keys={
+ \dirkeys@dolistedkeys@a{#1}\skv@gpostsetkeys
+ },
+ .remove postset keys={
+ \dirkeys@dolistedkeys@a{#1}\skvremovepostsetkeys
+ },
+ .gremove postset keys={
+ \dirkeys@dolistedkeys@a{#1}\skvgremovepostsetkeys
+ },
+ .undefine postset keys={
+ \skv@clfalse\dirkeys@dolistedkeys@b\skv@undefpostsetkeys
+ },
+ .gundefine postset keys={
+ \skv@cltrue\dirkeys@dolistedkeys@b\skv@undefpresetkeys
+ },
+ .option keys={
+ \dirkeys@dolistedkeys@a{#1}\skvoptionkeys
+ },
+ .goption keys={
+ \dirkeys@dolistedkeys@a{#1}\skvgoptionkeys
+ },
+ .remove option keys={
+ \dirkeys@dolistedkeys@a{#1}\skvremoveoptionkeys
+ },
+ .gremove option keys={
+ \dirkeys@dolistedkeys@a{#1}\skvgremoveoptionkeys
+ },
+ .nonoption keys={
+ \dirkeys@dolistedkeys@a{#1}\skvnonoptionkeys
+ },
+ .gnonoption keys={
+ \dirkeys@dolistedkeys@a{#1}\skvgnonoptionkeys
+ },
+ .remove nonoption keys={
+ \dirkeys@dolistedkeys@a{#1}\skvremovenonoptionkeys
+ },
+ .gremove nonoption keys={
+ \dirkeys@dolistedkeys@a{#1}\skvgremovenonoptionkeys
+ },
+ .need value keys={
+ \dirkeys@dolistedkeys@a{#1}\skvneedvaluekeys
+ },
+ .gneed value keys={
+ \dirkeys@dolistedkeys@a{#1}\skvgneedvaluekeys
+ },
+ .remove need value keys={
+ \dirkeys@dolistedkeys@a{#1}\skvremoveneedvaluekeys
+ },
+ .gremove need value keys={
+ \dirkeys@dolistedkeys@a{#1}\skvgremoveneedvaluekeys
+ },
+ .forbid value keys={
+ \dirkeys@dolistedkeys@a{#1}\skvforbidvaluekeys
+ },
+ .gforbid value keys={
+ \dirkeys@dolistedkeys@a{#1}\skvgforbidvaluekeys
+ },
+ .remove forbid value keys={
+ \dirkeys@dolistedkeys@a{#1}\skvremoveforbidvaluekeys
+ },
+ .gremove forbid value keys={
+ \dirkeys@dolistedkeys@a{#1}\skvgremoveforbidvaluekeys
+ },
+ .save initial value keys={
+ \dirkeys@dolistedkeys@a{#1}\skvsaveinitialvaluekeys
+ },
+ .gsave initial value keys={
+ \dirkeys@dolistedkeys@a{#1}\skvgsaveinitialvaluekeys
+ },
+ .remove save initial value keys={
+ \dirkeys@dolistedkeys@a{#1}\skvremovesaveinitialvaluekeys
+ },
+ .gremove save initial value keys={
+ \dirkeys@dolistedkeys@a{#1}\skvgremovesaveinitialvaluekeys
+ },
+ .undefine save initial value keys={
+ \dirkeys@dolistedkeys@a{#1}\skvundefsaveinitialvaluekeys
+ },
+ .gundefine save initial value keys={
+ \dirkeys@dolistedkeys@a{#1}\skvgundefsaveinitialvaluekeys
+ },
+ {.disable keys,.disable key}={
+ \dirkeys@dolistedkeys@a{#1}\skvdisablekeys
+ },
+ {.disabled key message type,.disabled key exception type}={
+ \skvdisabledkeysmessagetype{#1}
},
- .preset keys=\dirkeys@dolistedkeys@a{#1}\skv@presetkeys,
- .gpreset keys=\dirkeys@dolistedkeys@a{#1}\skv@gpresetkeys,
- .remove preset keys=
- \dirkeys@dolistedkeys@a{#1}\skvremovepresetkeys,
- .gremove preset keys=
- \dirkeys@dolistedkeys@a{#1}\skvgremovepresetkeys,
- .undefine preset keys=
- \skv@clfalse\dirkeys@dolistedkeys@b\skv@undefpresetkeys,
- .gundefine preset keys=
- \skv@cltrue\dirkeys@dolistedkeys@b\skv@undefpresetkeys,
- .postset keys=\dirkeys@dolistedkeys@a{#1}\skv@postsetkeys,
- .gpostset keys=\dirkeys@dolistedkeys@a{#1}\skv@gpostsetkeys,
- .remove postset keys=\dirkeys@dolistedkeys@a{#1}\skvremovepostsetkeys,
- .gremove postset keys=\dirkeys@dolistedkeys@a{#1}\skvgremovepostsetkeys,
- .undefine postset keys=
- \skv@clfalse\dirkeys@dolistedkeys@b\skv@undefpostsetkeys,
- .gundefine postset keys=
- \skv@cltrue\dirkeys@dolistedkeys@b\skv@undefpresetkeys,
- .need value keys=\dirkeys@dolistedkeys@a{#1}\skvneedvaluekeys,
- .gneed value keys=\dirkeys@dolistedkeys@a{#1}\skvgneedvaluekeys,
- .remove need value keys=
- \dirkeys@dolistedkeys@a{#1}\skvremoveneedvaluekeys,
- .gremove need value keys=
- \dirkeys@dolistedkeys@a{#1}\skvgremoveneedvaluekeys,
- .forbid value keys=
- \dirkeys@dolistedkeys@a{#1}\skvforbidvaluekeys,
- .gforbid value keys=
- \dirkeys@dolistedkeys@a{#1}\skvgforbidvaluekeys,
- .remove forbid value keys=
- \dirkeys@dolistedkeys@a{#1}\skvremoveforbidvaluekeys,
- .gremove forbid value keys=
- \dirkeys@dolistedkeys@a{#1}\skvgremoveforbidvaluekeys,
- .save initial value keys=
- \dirkeys@dolistedkeys@a{#1}\skvsaveinitialvaluekeys,
- .gsave initial value keys=
- \dirkeys@dolistedkeys@a{#1}\skvgsaveinitialvaluekeys,
- .remove save initial value keys=
- \dirkeys@dolistedkeys@a{#1}\skvremovesaveinitialvaluekeys,
- .gremove save initial value keys=
- \dirkeys@dolistedkeys@a{#1}\skvgremovesaveinitialvaluekeys,
- .undefine save initial value keys=
- \dirkeys@dolistedkeys@a{#1}\skvundefsaveinitialvaluekeys,
- .gundefine save initial value keys=
- \dirkeys@dolistedkeys@a{#1}\skvgundefsaveinitialvaluekeys,
- .disable keys=\dirkeys@dolistedkeys@a{#1}\skvdisablekeys,
- .disabled key message type={\skvdisabledkeysmessagetype{#1}},
% Choices are always appended; never prepended, since the parent
% key must first be set before choices are executed.
% <key1>/{<ch1>.do={<act1>},...,<ch-n>.do={<act-n>}},...,
% <key-n>/{<ch1>.do={<act1>},...,<ch-n>.do={<act-n>}}
- .state pattern=\dirkeys@savechoice{#1}{x0},
- .state pattern expand once=\dirkeys@savechoice{#1}{x1},
- .state pattern expand twice=\dirkeys@savechoice{#1}{x2},
- .state pattern expanded=\dirkeys@savechoice{#1}{xx},
- % {<key-i>,...,<key-j>}/{<stylelist-ij>},...,
- % {<key-n>,...,<key-m>}/{<stylelist-nm>}:
- .append style=\dirkeys@savestyle{#1}{app}{x0},
- .prepend style=\dirkeys@savestyle{#1}{prep}{x0},
- .append style expanded=\dirkeys@savestyle{#1}{app}{xx},
- .prepend style expanded=\dirkeys@savestyle{#1}{prep}{xx},
- .append style expand once=\dirkeys@savestyle{#1}{app}{x1},
- .prepend style expand once=\dirkeys@savestyle{#1}{prep}{x1},
- .append style expand twice=\dirkeys@savestyle{#1}{app}{x2},
- .prepend style expand twice=\dirkeys@savestyle{#1}{prep}{x2},
+ {.state pattern,.choice,.nominations}={
+ \dirkeys@savechoice{#1}{x0}
+ },
+ .state pattern expand once={
+ \dirkeys@savechoice{#1}{x1}
+ },
+ .state pattern expand twice={
+ \dirkeys@savechoice{#1}{x2}
+ },
+ {.state pattern expanded,.estate pattern,.enominations,.echoice}={
+ \dirkeys@savechoice{#1}{xx}
+ },
+ % {<key-i>,...,<key-j>}/{<slotlist-ij>},...,
+ % {<key-n>,...,<key-m>}/{<slotlist-nm>}:
+ {.append slot,.append slots,.slot,.slots,.style,.styles,.observers}={
+ \dirkeys@saveslots{#1}{app}{x0}
+ },
+ {.prepend slot,.prepend slots}={
+ \dirkeys@saveslots{#1}{prep}{x0}
+ },
+ {.append slot value expanded,.append slot expanded,
+ .append slots value expanded,.append slots expanded,
+ .eslot,.eslots,.estyle,.estyles}={
+ \dirkeys@saveslots{#1}{app}{xx}
+ },
+ {.prepend slot value expanded,.prepend slot expanded,
+ .prepend slots value expanded,.prepend slots expanded}={
+ \dirkeys@saveslots{#1}{prep}{xx}
+ },
+ {.append slot expand value once,.append slot expand once,
+ .append slots expand value once,.append slots expand once,
+ .slot expand once,.slots expand once,.style expand once,
+ .styles expand once}={
+ \dirkeys@saveslots{#1}{app}{x1}
+ },
+ {.prepend slot expand value once,.prepend slot expand once,
+ .prepend slots expand value once,.prepend slots expand once}={
+ \dirkeys@saveslots{#1}{prep}{x1}
+ },
+ {.append slot expand value twice,.append slot expand twice,
+ .append slots expand value twice,.append slots expand twice,
+ .slot expand twice,.slots expand twice,.style expand twice,
+ .styles expand twice}={
+ \dirkeys@saveslots{#1}{app}{x2}
+ },
+ {.prepend slot expand value twice,.prepend slot expand twice,
+ .prepend slots expand value twice,.prepend slots expand twice}={
+ \dirkeys@saveslots{#1}{prep}{x2}
+ },
% {<linklist-1>}/<mainkeylist-1>,...,{<linklist-n>}/<mainkeylist-n>:
- .append link=\dirkeys@savelink{#1}{app}{x0},
- .prepend link=\dirkeys@savelink{#1}{prep}{x0},
- .append link expanded=\dirkeys@savelink{#1}{app}{xx},
- .prepend link expanded=\dirkeys@savelink{#1}{prep}{xx},
- .append link expand once=\dirkeys@savelink{#1}{app}{x1},
- .prepend link expand once=\dirkeys@savelink{#1}{prep}{x1},
- .append link expand twice=\dirkeys@savelink{#1}{app}{x2},
- .prepend link expand twice=\dirkeys@savelink{#1}{prep}{x2},
- .list break=\skvbreaklooptrue,
- .args=\dirkeys@assignarg{#1}{x0},
+ {.append link,.append links,.link,.links}={
+ \dirkeys@savelinks{#1}{app}{x0}
+ },
+ {.prepend link,.prepend links}={
+ \dirkeys@savelinks{#1}{prep}{x0}
+ },
+ {.append link expanded value,.append link expanded,
+ .append links expanded value,.append links expanded,.elink,.elinks}={
+ \dirkeys@savelinks{#1}{app}{xx}
+ },
+ {.prepend link expanded value,.prepend link expanded,
+ .prepend links expanded value,.prepend links expanded}={
+ \dirkeys@savelinks{#1}{prep}{xx}
+ },
+ {.append link expand value once,.append link expand once,
+ .append links expand value once,.append links expand once,
+ .link expand once,.links expand once}={
+ \dirkeys@savelinks{#1}{app}{x1}
+ },
+ {.prepend link expand value once,.prepend link expand once,
+ .prepend links expand value once,.prepend links expand once}={
+ \dirkeys@savelinks{#1}{prep}{x1}
+ },
+ {.append link expand value twice,.append link expand twice,
+ .append links expand value twice,.append links expand twice,
+ .link expand twice,.links expand twice}={
+ \dirkeys@savelinks{#1}{app}{x2}
+ },
+ {.prepend link expand value twice,.prepend link expand twice,
+ .prepend links expand value twice,.prepend links expand twice}={
+ \dirkeys@savelinks{#1}{prep}{x2}
+ },
+ % .store value in={key1,key2}/<cmd>:
+ .store value in={
+ \dirkeys@savestores{#1}{x0}
+ },
+ {.store expanded value in,.store evalue in}={
+ \dirkeys@savestores{#1}{xx}
+ },
+ .store expanded once value in={
+ \dirkeys@savestores{#1}{x1}
+ },
+ .store expanded twice value in={
+ \dirkeys@savestores{#1}{x2}
+ },
+ {.list break,.listbreak,.break list}={
+ \skvbreaklooptrue
+ },
+ {.arg,.args}={
+ \dirkeys@assignarg{#1}{x0}
+ },
% Expand arguments of keys at key setting time, not at key definition:
- .args expanded=\dirkeys@assignarg{#1}{xx},
- .args expanded once=\dirkeys@assignarg{#1}{x1},
- .args expanded twice=\dirkeys@assignarg{#1}{x2},
- .set with defaults={
+ {.arg expanded,.args expanded}={
+ \dirkeys@assignarg{#1}{xx}
+ },
+ {.arg expand once,.args expand once}={
+ \dirkeys@assignarg{#1}{x1}
+ },
+ {.arg expand twice,.args expand twice}={
+ \dirkeys@assignarg{#1}{x2}
+ },
+ {.use defaults,.set with defaults}={
\dirkeys@dolistedkeys@a{#1}\dirkeys@setwithdefaults
},
- .unknown key handler={
- \dirkeys@dounknownkeyhandler{#1}
+ {.unknown key handler,.unknown option handler}={
+ \dirkeys@setunknownkeyhandler{#1}
},
% Redefine the default value macros of keys.
% .default values={keya=vala,...,keyn=valn}
- .default values={%
+ {.default value,.default values,.default,.defaults}={
\dirkeys@assigndefault{#1}
},
% Change the current values of keys.
% .assign values={keya=vala,...,keyn=valn}
- .assign values={%
+ {.assign value,.assign values}={
\dirkeys@assignvalue{#1}
},
+ {.inherit,.keys let,.key let}={
+ \dirkeys@keyslet{#1}
+ },
% A key inherits value from a key.
% .inherit values={keya1/keya2,...,keyn1/keyn2}
- .inherit values={%
- \dirkeys@inherit{value}{#1}
+ {.inherit value,.inherit values}={
+ \dirkeys@inheritproperty{value}{#1}
},
- .inherit callback={%
- \dirkeys@inherit{cbk}{#1}
+ {.inherit callback,.inherit callbacks,.inherit code}={
+ \dirkeys@inheritproperty{cbk}{#1}
},
- .inherit defaults={%
- \dirkeys@inherit{defa}{#1}
+ {.inherit default,.inherit defaults}={
+ \dirkeys@inheritproperty{defa}{#1}
},
- % .prepend values={keya=vala,...,keyn=valn}
- .prepend values={%
+ % .prepend values={key1=val1,...,keyn=valn}
+ {.prepend value,.prepend values}={
\dirkeys@addtocodeorvalue{pre}{value}{#1}
},
- .append values={%
+ {.append value,.append values}={
\dirkeys@addtocodeorvalue{app}{value}{#1}
},
- % .prepend code={keya=codea,...,keyn=coden}
- .prepend code={%
+ % .prepend code={key1=code1,...,keyn=coden}
+ {.prepend code,.prepend codes}={
\dirkeys@addtocodeorvalue{pre}{cbk}{#1}
},
- .append code={%
+ {.append code,.append codes}={
\dirkeys@addtocodeorvalue{app}{cbk}{#1}
},
},
- .new narg handlers={%
- .no such key={4}{%
- % All the parameters would have been despaced when this handler
- % is called. #1=prefix, #2=family, #3=key, #4=value.
- \skvifcsdefTF{#1@#2@handler}{%
+ .new narg handlers={
+ % All the parameters would have been despaced when '.no such key'
+ % is called. #1=prefix, #2=family, #3=key, #4=value.
+ .no such key={4}{
+ \skvifcsdefTF{#1@#2@handler}{
\csname#1@#2@handler\endcsname{#1}{#2}{#3}{#4}
- }{%
- \skv@err{Key '#3' is not in family '#1/#2'}\@ehd
- }%
+ }{
+ \skv@err{Key '#3' is not in family '#1/#2'}\skv@ehd
+ }
},
- .add style={2}{%
- \skvusehandler{.prepend style}{#1}%
- \skvusehandler{.append style}{#2}%
+ .add slot={2}{
+ \skvusehandler{.prepend slot}{#1}
+ \skvusehandler{.append slot}{#2}
},
- .add code={2}{%
- \skvusehandler{.prepend code}{#1}%
- \skvusehandler{.append code}{#2}%
+ .add code={2}{
+ \skvusehandler{.prepend code}{#1}
+ \skvusehandler{.append code}{#2}
},
- .add value={2}{%
- \skvusehandler{.prepend value}{#1}%
- \skvusehandler{.append value}{#2}%
+ .add value={2}{
+ \skvusehandler{.prepend value}{#1}
+ \skvusehandler{.append value}{#2}
},
% .get value={<pref>}{<fam>}{<key>}<cmd>
- .get value={4}{%
- \skvifcsdefTF{#1/#2/#3.@value}{%
- \skvifescapedTF{#4}{%
- \skvletcs#4{#1/#2/#3.@value}%
- }{%
- \skv@err{Token '\detokenize{#4}' isn't escaped}\@ehd
- }%
- }{%
+ .get value={4}{
+ \skvifnamedefTF{#1/#2/#3.@value}{
+ \skvifescapedTF{#4}{
+ \skvletcs#4{#1/#2/#3.@value}
+ }{
+ \skv@err{Token '\detokenize{#4}' isn't escaped}\skv@ehd
+ }
+ }{
\skv@err{Key '#3' isn't defined or has
- \MessageBreak no value in '#1/#2'}\@ehd
- }%
+ \MessageBreak no value in '#1/#2'}\skv@ehd
+ }
},
- % '.try set keys' doesn't use the active prefixes and families within
- % \dirkeys. The prefix, families and other options are to be supplied
- % in the argument #1. The key .key values (or .kv) is used to
- % supply the key-value pairs.
- % .try set keys={<options>}
- .try set keys={1}{\dirkeys@trysetkeys{#1}},
- % 'search also' set keys.
- % .sa set keys={<options>}
- .sa set keys={1}{\dirkeys@sasetkeys{#1}},
- % .set boolean handler={<handler>}{<boolean>}{<value>}
- .set boolean handler={3}{%
+ % .set boolean handler={<handler>}{<boolean>}{<boolean.value>}
+ % See example use above.
+ .set boolean handler={3}{
\dirkeys@setbooleanhandler{#1}{#2}{#3}
},
},
- .handler let={%
- .exec=.exec code,
- .handlers let=.handler let,
- .prefix=.prefixes, .change prefix=.prefix, .cp=.prefix,
- .add prefix=.add prefixes,
- .ignore prefix=.ignore prefixes,
- .restore prefix=.restore prefixes,
- .hp=.holder prefix,
- .family=.families, .change family=.family, .cf=.family,
- .add family=.add families,
- .ignore family=.ignore families,
- .restore family=.restore families,
- .root=.roots, .change root=.roots, .cd=.roots,
- .path=.roots, .paths=.roots, .change path=.roots,
- .add root=.add roots,
- .add path=.add roots, .add paths=.add roots,
- .ignore root=.ignore roots,
- .ignore path=.ignore roots, .ignore paths=.ignore roots,
- .restore root=.restore roots,
- .restore path=.restore roots, .restore paths=.restore roots,
- .push prefix=.push prefixes, .pop prefix=.pop prefixes,
- .push family=.push families, .pop family=.pop families,
- .push path=.push paths, .pop path=.pop paths,
- .push hp=.push holder prefix, .pop hp=.pop holder prefix,
- .ignore key=.ignore keys, .restore key=.restore keys,
- .define key=.define keys, .new key=.new keys,
- .initialize after define=.initialize keys after define,
- .save initial values=.save initial values of keys,
- .set=.set keys, .setkeys=.set keys,
- .set*=.set keys*, .setkeys*=.set keys*,
- .setkeys save unknown=.set keys*,
- .setrmkeys=.set rmkeys,
- .set remaining keys=.set rmkeys,
- .setrmkeys*=.set rmkeys*,
- .set remaining keys*=.set rmkeys*,
- .presetkeys=.preset keys, .initial values=.preset keys,
- .postsetkeys=.postset keys,
- .try set=.try set keys,
- .sa set=.sa set keys, .search also set keys=.sa set keys,
- .use defaults=.set with defaults,
- .restrict values=.state pattern,
- .nominations=.state pattern,
- .singleton=.state pattern,
- .estate pattern=.state pattern expanded,
- .esingleton=.state pattern expanded,
- .style=.append style,
- .styles=.append style,
- .estyle=.append style expanded,
- .style expand once=.append style expand once,
- .style expand twice=.append style expand twice,
- .link=.append link,
- .links=.append link,
- .elink=.append link expanded,
- .link expand once=.append link expand once,
- .link expand twice=.append link expand twice,
- .listbreak=.list break, .break list=.list break,
- .new handler=.new handlers, .define handler=.define handlers,
- .kill handler=.kill handlers,
- .initial value=.initial values,
- .default value=.default values,.default=.default values,
- .defaults=.default values,
- .assign value=.assign values,
- .inherit value=.inherit values,
- .inherit default=.inherit defaults,
- .inherit code=.inherit callback,
- .prepend value=.prepend values,
- .append value=.append values,
- .disabled option message type=.disabled key message type,
- .message type when disabled key is invoked=.disabled key message type,
- .message type when disabled option is invoked=.disabled key message type,
- .unknown option handler=.unknown key handler,
+ .handlers let reserved={
+ {.disabled option message type,
+ .message type when disabled key is invoked,
+ .message type when disabled option is invoked
+ }=.disabled key message type,
},
}
% \skvpatchcmd[<prefix>]{<cmd>}{<search>}{<replace>}{<success>}{<fail>}
+%
\skvrobustdef*\skvpatchcmd{%
\begingroup
\@makeother{\#}\endlinechar\m@ne
@@ -6846,30 +8339,32 @@
\edef\skv@tempb##1{##1\detokenize{#1}\skvrelax}%
\skv@tempb{\expandafter\skv@tempa\meaning#2}%
}
-\skvrobustdef*\skvifmacroTF#1{%
- \skvifntypeTF{#1}{%
- \begingroup
- \edef\skv@tempa##1{\def##1####1\detokenize{macro}:####2\skvrelax}%
- \skv@tempa\skv@tempa{%
- \expandafter\endgroup\ifx\@nnil##2\@nnil
- \expandafter\@secondoftwo
- \else
- \expandafter\@firstoftwo
- \fi
- }%
- \edef\skv@tempb##1{##1\detokenize{macro}:\skvrelax}%
- \skv@tempb{\expandafter\skv@tempa\meaning#1}%
- }{%
- \@secondoftwo
- }%
+\edef\skv@begindoctoks{\string\begin\string{\string\document\string}}
+\skvrobustdef*\skvAtBeginEnvironment#1{%
+ \skvaftercs\skvappendtomacro{lps@atbegin@#1@hook}%
+}
+\skvrobustdef*\skvAtEndEnvironment#1{%
+ \skvaftercs\skvappendtomacro{lps@atend@#1@hook}%
}
-\skvrobustdef*\skvifmacroFT#1{\skvifmacroTF{#1}\@secondoftwo\@firstoftwo}
+\skvpatchcmd\begin
+ {\csname#1\endcsname}
+ {\skvcsuse{lps@atbegin@#1@hook}\csname#1\endcsname}
+ {}
+ {\skv@err{Patching '\string\begin' failed!\MessageBreak
+ '\string\skvAtBeginEnvironment' will not work\@gobble}\@ehd
+ }
-%\skvxzapspaces{\detokenize{\begin{\document}}}\skv@begindoctoks
-\edef\skv@begindoctoks{\string\begin\string{\string\document\string}}
+\skvpatchcmd\end
+ {\csname end#1\endcsname}
+ {\skvcsuse{lps@atend@#1@hook}\csname end#1\endcsname}
+ {}
+ {\skv@err{Patching '\string\end' failed!\MessageBreak
+ '\string\skvAtEndEnvironment' will not work\@gobble}\@ehd
+ }
\skv@core@restorecodes
+
\endinput
%% End of file 'skeyval-core.tex'.
diff --git a/Master/texmf-dist/tex/latex/skeyval/skeyval-for.tex b/Master/texmf-dist/tex/latex/skeyval/skeyval-for.tex
index 309a5649c93..a61c4f0c499 100644
--- a/Master/texmf-dist/tex/latex/skeyval/skeyval-for.tex
+++ b/Master/texmf-dist/tex/latex/skeyval/skeyval-for.tex
@@ -1,5 +1,5 @@
%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
-% This is file 'skeyval-for', version 1.1a, 2012/10/16. %
+% This is file 'skeyval-for.tex', version 1.2, 2013/02/10. %
% %
% This package and accompanying files may be distributed and/or %
% modified under the conditions of the LaTeX Project Public License, %
@@ -23,7 +23,7 @@
% skeyval-pstkey.sty, skeyval-pstkey.tex, skeyval-testclass.cls, %
% and skeyval-testpkg.sty. %
% %
-% Copyright (c) 2010-2012 Ahmed Musa (amusa22@gmail.com). %
+% Copyright (c) 2010-2013 Ahmed Musa (amusa22@gmail.com). %
%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
\begingroup%
@@ -59,16 +59,21 @@
\expandafter\let\csname skeyval-for-loaded\endcsname\endinput
\ifx\ProvidesFile\@undefined
- \message{File 'skeyval-for.tex' 2012/10/16 v1.1a
+ \message{File 'skeyval-for.tex' 2013/02/10 v1.2
Loops for skeyval package (AM)}
\else
\ProvidesFile{skeyval-for.tex}
- [2012/10/16 v1.1a Loops for skeyval package (AM)]
+ [2013/02/10 v1.2 Loops for skeyval package (AM)]
\@addtofilelist{skeyval-for.tex}
\fi
-\skvrobustdef*\skv@nostackerr{\skv@err{You've called an empty stack}\@ehd}
-% \skvsavestate<base-fn>{<fn-list>}<counter>
+\skvrobustdef*\skv@nostackerr{%
+ \skv@err{You've called an empty stack}\skv@ehd
+}
+% \skvsavestate<base-fn>{<fn-list>}<counter-number>
+%
+% See file skeyval-core.tex for \skvpushfunctions and \skvpopfunctions.
+%
\skvrobustdef*\skvsavestate#1#2#3{%
\skvgadvanceno#3\@ne
\begingroup
@@ -80,13 +85,13 @@
\def\do##1{\let\skvnoexpandcs{\skv@prova{##1}}\noexpand##1}%
\edef\reserved@a{\endgroup#2}\reserved@a
}
-% \skvrestorestate<base-fn><counter>
+% \skvrestorestate<base-fn><counter-number>
\skvrobustdef*\skvrestorestate#1#2{%
\begingroup
\let\nostack\skv@nostackerr
\edef\skv@elt{\skvnoexpandcs{\skvremovescape#1@skv@stack}}%
\expandafter\ifx\skv@elt\relax
- \skv@err{Stack of '\noexpand#1' is undefined}\@ehd
+ \skv@err{Stack of '\noexpand#1' is undefined}\skv@ehd
\fi
\edef\skv@prova{\skvexpandtwice\skv@elt}%
\edef\skv@provb##1##{\endgroup##1\gdef\skvexpandonce\skv@elt}%
@@ -95,60 +100,78 @@
}
\skvnewregisters\bool{%
- \ifskvbreakloop\ifforeachlastitem
- \ifskvprocessempty\ifskv@foreach@swa
- \ifskv@foreach@swb\ifskv@foreach@parenth
+ \ifbreakallforeachloops,\ifskvbreakloop,\ifforeachlastitem,
+ \ifskvprocessempty,\ifskv@foreach@swa,\ifskv@foreach@swb,
+ \ifskv@foreach@parenth,\ifskv@useemptylist
}
-\skvnewnumbers[skv@]{csvdepth,dolistcnt}
-
-\skvrobustdef*\skv@usetempst#1#2{%
- \edef#2{\skvifdefboolTF{skv@tempst}\skvexpandonce\unexpanded{#1}}%
+\skvnewlet\skvbreakloop\skvbreaklooptrue
+\skvnewlet\breaknewforeach\skvbreaklooptrue
+% \breakallforeachloops will break all current loops (inner and outer):
+\skvnewdef*\breakallforeachloops{%
+ \skvbreaklooptrue\breakallforeachloopstrue
}
+
+\skvnewnumbers[skv@]{csvdepth,dolistdepth}
%
% \skvdolist{<parser>}{<list>}<holdercmd>{<callback>}
% \skvdolist*{<parser>}{<listcmd>}<holdercmd>{<callback>}
-%
-% 1. \skvdolist can process both csv and tsv/nsv lists.
-% 2. This can be nested to any depth, with different parsers on each
-% level.
-% 3. This will not process an empty list; see \skvecommaloop.
+% \skvparselist{<parser>}{<list>}<holdercmd>{<callback>}
+% \skvparselist*{<parser>}{<listcmd>}<holdercmd>{<callback>}
+% \skvprocesslist{<parser>}{<list>}<holdercmd>{<callback>}
+% \skvprocesslist*{<parser>}{<listcmd>}<holdercmd>{<callback>}
+%
+% 1. These macros can process both csv and tsv/nsv lists. Use empty
+% <parser> for tsv lists.
+% 2. These macros can be nested to any depth, with different parsers
+% on each level.
+% 3. \skvdolist and \skvparselist will not process an empty list, but
+% \skvprocesslist will do so.
% 4. For comma lists, \skvcommaloop and \skvcommaparse are faster.
% See later.
-% 5. For processing kv lists, use \skvkvparse.
+% 5. For processing kv lists, use \skvparsekvlist.
%
-\skvrobustdef*\skvdolist{\skv@testst\skv@dolist}
+\skvrobustdef*\skvdolist{\skv@useemptylistfalse\skv@testst\skv@dolist}
\skvrobustdef*\skv@dolist#1#2#3#4{%
- \skvgadvanceno\skv@dolistcnt\@ne
+ % \skvlistcount is used by listkeys.
+ \skvsavestate\skvdolist{%
+ \do\skv@dolist@callback
+ \do\skv@dolist@a\do\skvlistcount\do\ifskv@useemptylist
+ }\skv@dolistdepth
\skv@usetempst{#2}#3%
- \def\skv@dolist@a{skv@dolist@\skvrom\skv@dolistcnt}%
- \skvcsdef{\skv@dolist@a}##1##2##3#1{%
- \skvifstrcmpTF{##3}{\skv@dolist@nil}{%
+ \edef\skv@dolist@callback{\unexpanded{#4}}%
+ \def\skvlistcount{0}%
+ \def\skv@dolist@a##1##2#1{%
+ \skvifstrcmpTF{##2}{\skv@dolist@nil}{%
% To allow nesting of loop:
\skvbreakloopfalse
}{%
- \edef##1{\unexpanded{##3}}%
- ##2\relax
+ \edef##1{\unexpanded{##2}}%
+ \edef\skvlistcount{\the\numexpr\skvlistcount+1}%
+ \skv@dolist@callback\relax
\ifskvbreakloop
\skvbreakloopfalse
\begingroup
- \skvcsdef{\skv@dolist@a}####1\skv@dolist@nil#1{\endgroup}%
+ \def\skv@dolist@a####1####2\skv@dolist@nil#1{%
+ \endgroup
+ \edef\skvremainder{\unexpanded{####2}}%
+ }%
\fi
- \@nameuse{\skv@dolist@a}##1{##2}%
+ \skv@dolist@a{##1}%
}%
}%
- \skvifemptyTF#3{}{%
- \edef\reserved@a{\unexpanded{\@nameuse{\skv@dolist@a}#3{#4}}}%
- \expandafter\reserved@a#3#1\skv@dolist@nil#1%
+ \ifskv@useemptylist
+ \def\reserved@a##1##2##3{##3}%
+ \else
+ \let\reserved@a\skvifemptyTF
+ \fi
+ \reserved@a#3{}{%
+ \expandafter\skv@dolist@a\expandafter#3#3#1\skv@dolist@nil#1%
}%
- \skvgadvanceno\skv@dolistcnt\m@ne
+ \skvrestorestate\skvdolist\skv@dolistdepth
}
-
% First normalize the list before parsing.
-%
-% \skvparselist{<parser>}{<list>}<holdercmd>{<callback>}
-% \skvparselist*{<parser>}{<listcmd>}<holdercmd>{<callback>}
-%
-\skvrobustdef*\skvparselist{\skv@testst\skv@parselist}
+\skvrobustdef*\skvparselist{\skv@useemptylistfalse\skv@testst\skv@parselist}
+\skvrobustdef*\skvprocesslist{\skv@useemptylisttrue\skv@testst\skv@parselist}
\skvrobustdef*\skv@parselist#1#2#3{%
\skv@usetempst{#2}#3%
\skvcsvnormalize[#1]#3%
@@ -156,14 +179,11 @@
\skv@dolist{#1}#3#3%
}
-\skvifdefinable\listbreaker{\let\listbreaker\relax}
-\skvifdefinable\listpauser{\let\listpauser\relax}
-\skvnewdef*\skv@listbreakertoks{\listbreaker}
-\skvnewdef*\skv@listpausertoks{\listpauser}
-
+\skvnewlet\foreachlistbreaker\relax
+\skvnewlet\foreachlistpauser\relax
+\skvnewdef*\skv@listbreakertoks{\foreachlistbreaker}
+\skvnewdef*\skv@listpausertoks{\foreachlistpauser}
\skvnewlet\skvprocessempty\skvprocessemptytrue
-\skvletmanytocmd{\skvbreakloop\interruptloop\skvbreakforeach
- \interruptforeach}\skvbreaklooptrue
% Reversing tokens:
\skvnewdef*\skvreverse#1{\skv@reverse#1\skv@reverse@stop}
@@ -217,14 +237,14 @@
}
% A version of LaTeX's \@tfor that can parse undoubled parameter
-% characters.
+% characters and terminate the loop by using \skvbreakloop.
%
% \skvtfor<holder.cmd>:={<list>}\do{<callback>}
% \skvtfor*<holder.cmd>:={<listcmd>}\do{<callback>}
%
% Example:
%
-% \skvnewregister\count\nr
+% \skvnewregister\count{\nr}
% \skvtfor\x:=a \ifx {\def\x#1{#1}} \fi\do{%
% \nr\z@
% \skvtfor\y:=12345\do{%
@@ -239,7 +259,7 @@
\skvrobustdef*\skv@tfor#1:={\skv@tf@r#1 }
\skvrobustdef\skv@tf@r#1#2\do#3{%
\edef#1{\skvtrimspace{#2}}%
- \edef#1{\skvifboolTF{skv@tempst}\skvexpandtwice\skvexpandonce{#1}}%
+ \edef#1{\skvifdefboolTF{skv@tempst}\skvexpandtwice\skvexpandonce{#1}}%
\skvifemptyTF#1{}{%
\skvbreakloopfalse
\expandafter\skv@tforloop#1\skv@tfor@nil\skv@tfor#1{#3}%
@@ -266,23 +286,29 @@
%+++++++++++++++ Non-expandable comma loops ++++++++++++++%%
%
% 1. These follow from \skvdolist and \skvparselist, but they are
-% specialized for comma lists and they are faster.
-% 2. They can be nested.
-% 3. \skvecommaloop needs \skv@c@mmaloop.
+% specialized for comma lists and they are faster, since they don't
+% stack any state.
+% 2. There is no fear of parameter characters in <callback> being mixed
+% with those of \skv@commaloop@picknext.
+% 2. They can be nested to any depth.
%
% \skvcommaloop{<list>}<holder-cmd>{<callback>}
% \skvcommaloop*{<listcmd>}<holder-cmd>{<callback>}
%
+% Example:
+%
+% \skvcommaloop{x#1,y#1}\tempa{\edef\xx#1{#1\tempa}}
+%
\skvrobustdef*\skvcommaloop{\skv@testst\skv@commaloop}
\skvrobustdef\skv@commaloop#1#2#3{%
\skv@usetempst{#1}#2%
% Don't put \skvcsvnormalize#2 here. Use \skvcommaparse instead.
% Some callers of \skvcommaloop already have their lists normalized.
\skvifxTF#2\@empty{}{%
- \skvexpandnext{\skv@c@mmaloop#2{#3}}#2,\skv@commaloop@nil,%
+ \skvexpandnext{\skv@commaloop@picknext#2{#3}}#2,\skv@commaloop@nil,%
}%
}
-\skvrobustdef\skv@c@mmaloop#1#2#3,{%
+\skvrobustdef\skv@commaloop@picknext#1#2#3,{%
\skvifstrcmpTF{#3}{\skv@commaloop@nil}{%
\skvbreakloopfalse
}{%
@@ -291,9 +317,12 @@
\ifskvbreakloop
\skvbreakloopfalse
\begingroup
- \long\def\skv@c@mmaloop##1\skv@commaloop@nil,{\endgroup}%
+ \long\def\skv@commaloop@picknext##1##2##3\skv@commaloop@nil,{%
+ \endgroup
+ \edef\skvremainder{\unexpanded{##3}}%
+ }%
\fi
- \skv@c@mmaloop#1{#2}%
+ \skv@commaloop@picknext#1{#2}%
}%
}
%
@@ -306,7 +335,7 @@
%
\skvrobustdef\skvecommaloop{\skv@testst\skv@ecommaloop}
\skvrobustdef\skv@ecommaloop#1#2#3{%
- \edef#2{\unexpanded{\skv@c@mmaloop#2{#3}}}%
+ \edef#2{\unexpanded{\skv@commaloop@picknext#2{#3}}}%
\ifskv@tempst\expandafter\expandafter\fi#2#1,\skv@commaloop@nil,%
}
%
@@ -325,30 +354,17 @@
% \skvkvparse{<list>}<cmd>{<callback>}
% \skvkvparse*{<listcmd>}<cmd>{<callback>}
%
-% \skvkvparse is as \skvcommaloop but will first normalize <list> using
-% \skvkvnormalize.
+% 1. \skvkvparse is as \skvcommaloop but will first normalize <list> using
+% \skvkvnormalize.
+% 2. It is meant for processing key-value lists.
%
\skvrobustdef*\skvkvparse{\skv@testst\skv@kvparse}
-\skvnewlet\skvparsekeyvals\skvkvparse
+\skvnewlet\skvparsekvlist\skvkvparse
\skvrobustdef\skv@kvparse#1#2#3{%
\skv@usetempst{#1}#2%
\skvkvnormalize#2%
\skvcommaloop*#2#2{#3}%
}
-% \skvcommaprocess{<list>}<holder.cmd>
-% \skvcommaprocess*{<listcmd>}<holder.cmd>
-%
-% If <list> or <listcmd> is a single item, then no looping is required.
-%
-\skvrobustdef*\skvcommaprocess{\skv@testst\skv@commaprocess}
-\skvrobustdef*\skv@commaprocess#1#2#3{%
- \skv@usetempst{#1}#2%
- \skvxifinTF{,}{\skvoxdetok#2}{%
- \skvcommaparse*#2#2{#3}%
- }{%
- \skvdespacecontent#2#3%
- }%
-}
% \skvcountelements[<parser>]{<list>}{<return.cmd>}
% \skvcountelements*[<parser>]{<listcmd>}{<return.cmd>}
\skvrobustdef*\skvcountelements{\skv@teststopt\skv@countelements,}
@@ -402,14 +418,20 @@
%
% 3. Elements of the form (a,b) and [a,b] are grabbed together.
%
-% 4. Use \interruptforeach to break out of the loop prematurely.
+% 4. Use \breaknewforeach to break out of the loop prematurely.
%
% 5. \newforeach can be nested.
-
-% \skv@foreach@sisterdepth must be different from \foreachdepth,
+%
+% 6. The star (*) variant of \newforeach is equivalent to using the
+% key 'list is a macro' (or *) in <options>.
+%
+% \skv@foreach@holderdepth must be different from \foreachnestdepth,
% to avoid confusing two different stacks.
-\skvnewnumbers{foreachdepth,skv@foreach@sisterdepth,skv@foreach@nra,%
- skv@warnsubparser}
+\skvnewnumbers{foreachnestdepth,skv@foreach@holderdepth,%
+ skv@foreach@nra,skv@warnsubparser}
+% \newforeach will not accept \skvifstreq or \skvifstrcmpTF because
+% they don't start with '\if'. So we introduce \ifforeachstrcmp:
+\skvnewlet\ifforeachstrcmp\skvifstreq
\skvnewdef*\skv@foreach@onlyinitially{}
\skvrobustdef*\skvforeachonlyinitially#1{%
\edef\skv@foreach@onlyinitially{%
@@ -496,9 +518,9 @@
\appendtoendforeach[#1]{#2}%
}
-% \skv@foreach@fi must use \detokenize. Don't change to \string!
-\skvnewedef*\skv@foreach@fi{\detokenize{\fi}}
-\skvnewedef*\skv@foreach@if{\string\if}
+% \skv@foreach@fi@toks must use \detokenize. Don't change to \string!
+\skvnewedef*\skv@foreach@fi@toks{\detokenize{\fi}}
+\skvnewedef*\skv@foreach@if@toks{\string\if}
% \skv@foreach@ifacceptkv and \skv@foreach@maketester must come
% before the initialization of keys:
@@ -508,7 +530,7 @@
\edef\skv@prova{\unexpanded{#1}}%
\ifnum0>\numexpr0\ifx\skv@prova\@empty-1\else
\ifx\skv@prova\@nnil-1\else+0\fi\fi\relax\relax
- \skv@err{Invalid syntax '\detokenize{#1}'}\@ehd
+ \skv@err{Invalid syntax '\detokenize{#1}'}\skv@ehd
\else
\edef\next{\unexpanded{#2}}%
\fi
@@ -522,12 +544,12 @@
}{%
\skv@err{Value of key '#1' must
\MessageBreak be escaped: the holder macro
- \MessageBreak to be evaluated}\@ehd
+ \MessageBreak to be evaluated}\skv@ehd
}%
}{%
\skv@err{Value of key '#1' must
\MessageBreak be only one token: the holder
- \MessageBreak macro to be evaluated}\@ehd
+ \MessageBreak macro to be evaluated}\skv@ehd
}%
}
% \skv@foreach@maketester{<cond>}<cond.tester.cmd>{<flag>}
@@ -536,7 +558,14 @@
% are allowed. Restricting the type of allowed conditionals is
% necessary for auto syntax checking.
% 2. <flag> is either 0 or 1, signifying whether or not the condition
-% should be entered in postcallback.
+% should be entered in postcallback. This is because
+% \skv@foreach@maketester is called (by key 'loop stopper') for
+% formating the premature exit condition and (in
+% \skv@foreach@parsecountin and \skv@foreachfox@parsecountin) for the
+% condition for counting an item of the list. In the latter case,
+% there is no need to enter the formated
+% condition in the postcallback, since it it is entered in the
+% 'afterprecallback' or (in the case of \foreachfox) in 'precallback'.
%
% Examples: \ifnum\x>10\fi, \ifx\x\cmd\fi.
%
@@ -546,10 +575,11 @@
\begingroup
\edef\skv@prova{\detokenize{#1}}%
\skvifblankTF{#1}{%
- \skv@err{A blank conditional given in \string\newforeach}\@ehd
+ \skv@err{A blank conditional has been given in
+ \MessageBreak\string\newforeach or a similar command}\skv@ehd
}{%
- \skvxifinTF{\skv@foreach@fi\relax}{\detokenize{#1}\relax}{%
- \skvxifinTF{\relax\skv@foreach@if}{\relax\detokenize{#1}}{%
+ \skvxifinTF{\skv@foreach@fi@toks\relax}{\detokenize{#1}\relax}{%
+ \skvxifinTF{\relax\skv@foreach@if@toks}{\relax\detokenize{#1}}{%
\edef#2{\noexpand\skvifconditionTF\unexpanded{#1}}%
\ifnum#3=\@ne
\skv@foreach@addtocallback{post}{%
@@ -561,7 +591,7 @@
{Invalid, possibly unbalanced, conditional '\skv@prova'}%
}%
}{%
- \skv@err{Invalid conditional '\skv@prova'}\@ehd
+ \skv@err{Invalid conditional '\skv@prova'}\skv@ehd
}%
}%
\skvexpanded{\endgroup
@@ -602,30 +632,26 @@
\def\skv@foreach@subparser{/}
;
parser/{,}/
- \ifskvindef\else
- \edef\skv@foreach@parser{\unexpanded{#1}}
- \skvstripouterbraces{2}\skv@foreach@parser
- \skvxifntypeTF{\detokenize{#1}}{%
- \begingroup
- % It is assumed that every n-type parser and subparser
- % must have catcode 12:
- \skvexpandnext{\catcode`}\skv@foreach@parser=12\relax
- \skv@rescan\skv@foreach@parser
- \skvaftergroupdef\skv@foreach@parser\endgroup
- }{}
- \fi
+ \edef\skv@foreach@parser{\unexpanded{#1}}
+ \skvstripouterbraces{2}\skv@foreach@parser
+ \skvxifntypeTF{\detokenize{#1}}{%
+ \begingroup
+ % It is assumed that every n-type parser and subparser
+ % must have catcode 12:
+ \skvexpandnext{\catcode`}\skv@foreach@parser=12\relax
+ \skvrescan\skv@foreach@parser
+ \skvaftergroupdef\skv@foreach@parser\endgroup
+ }{}
;
subparser/{/}/
- \ifskvindef\else
- \edef\skv@foreach@subparser{\unexpanded{#1}}
- \skvstripouterbraces{2}\skv@foreach@subparser
- \skvxifntypeTF{\detokenize{#1}}{
- \begingroup
- \skvexpandnext{\catcode`}\skv@foreach@subparser=12\relax
- \skv@rescan\skv@foreach@subparser
- \skvaftergroupdef\skv@foreach@subparser\endgroup
- }{}
- \fi
+ \edef\skv@foreach@subparser{\unexpanded{#1}}
+ \skvstripouterbraces{2}\skv@foreach@subparser
+ \skvxifntypeTF{\detokenize{#1}}{
+ \begingroup
+ \skvexpandnext{\catcode`}\skv@foreach@subparser=12\relax
+ \skvrescan\skv@foreach@subparser
+ \skvaftergroupdef\skv@foreach@subparser\endgroup
+ }{}
;
terminator,callback terminator/{;}/
\edef\skv@foreach@terminator{\unexpanded{#1}}%
@@ -633,27 +659,40 @@
;
% process up to = <nr>
% Maximum number of items to process:
- process up to,process up to number/\@nil/
- \ifskvindef\else
+ process up to,process up to number//
+ \skviflacus#1\then\else
+ \skvensureinteger{process up to}{#1}%
\def\skv@foreach@processupto{#1}%
- \ifx\skv@foreach@processupto\@nnil\else
- \skv@ensureinteger{process up to}{#1}%
- \fi
+ \skvstripouterbraces{2}\skv@foreach@processupto
\fi
;
process empty list/true/
\edef\skv@foreach@processempty{0\skvifstrcmpTF{true}{#1}01}%
/true,false
;
- % Eg, exit when=\ifnum\x=20\fi
+ % 'break=<condition>'
+ % Break list processing when <condition> is satisfied. <condition> must
+ % be a balanced plain TeX conditional. Eg, 'exit when={\ifnum\x=20\fi}'.
+ % Notice the use of outer braces in '{\ifnum\x=20\fi}'. This avoids
+ % conflicting the two equality signs: for the key-value and for number
+ % testing.
.exec/\let\skv@foreach@exittester\@secondoftwo;
- loop stopper,exit when/\if01\fi/
- \ifskvindef\else
- \edef\skv@tempa{\unexpanded{#1}}%
- \skvstripouterbraces{2}\skv@tempa
- \expandafter\skv@foreach@maketester\expandafter
- {\skv@tempa}\skv@foreach@exittester\@ne
- \fi
+ break,loop stopper,exit when/\if01\fi/
+ \edef\skv@tempa{\unexpanded{#1}}%
+ \skvstripouterbraces{2}\skv@tempa
+ \skvexpbracenext\skv@foreach@maketester\skv@tempa
+ \skv@foreach@exittester\@ne
+ ;
+ % Java-type of continue: If the user wants to ignore the callback for
+ % some items, he can instantiate the key 'condition=<condition>'.
+ % <condition> must be a balanced plain TeX conditional. Eg,
+ % continue={\ifnum\x=20\fi}.
+ .exec/\let\skv@foreach@continuetester\@secondoftwo;
+ continue,ignore callback/\if01\fi/
+ \edef\skv@tempa{\unexpanded{#1}}%
+ \skvstripouterbraces{2}\skv@tempa
+ \skvexpbracenext\skv@foreach@maketester\skv@tempa
+ \skv@foreach@continuetester\skvz@
;
% Eg, 'evaluate = \x as \z using \numexpr\x*2'. 'as' and 'using', and the
% tokens after them, can be missing, but the formula must be complete.
@@ -724,39 +763,28 @@
\skv@foreach@parserecall{#1}%
}%
;
- item counter,counter/\@nil/
- \ifskvindef\else
- \edef\skv@prova{\unexpanded{#1}}%
- \ifx\skv@prova\@nnil
- \skv@err{Invalid empty value for key 'item counter'}\@ehd
- \else
- \skvifescapedTF{#1}{%
- \let\skv@foreach@itemcounter\skv@prova
- }{%
- \skv@err{Non-escaped value '\detokenize{#1}'
- \MessageBreak for key 'item counter'}\@ehd
- }%
- \fi
- \fi
+ item counter,counter/\foreachdefaultitemcounter/
+ \skvifescapedTF{#1}{%
+ \def\skv@foreach@itemcounter{#1}%
+ }{%
+ \skv@err{Non-escaped value '\detokenize{#1}'
+ \MessageBreak for key 'item counter'}\skv@ehd
+ }%
;
- list breaker/\listbreaker/
- \ifskvindef\else
- \edef\skv@prova{\unexpanded{#1}}%
- \ifx\skv@prova\@empty
- \skv@err{Invalid empty value for key 'list breaker'}\@ehd
- \else
- \let\skv@listbreakertoks\skv@prova
- \fi
+ list breaker/\foreachlistbreaker/
+ \edef\skv@prova{\unexpanded{#1}}%
+ \ifx\skv@prova\@empty
+ \skv@err{Invalid empty value for key 'list breaker'}\skv@ehd
+ \else
+ \let\skv@listbreakertoks\skv@prova
\fi
;
- list pauser/\listpauser/
- \ifskvindef\else
- \edef\skv@prova{\unexpanded{#1}}%
- \ifx\skv@prova\@empty
- \skv@err{Invalid empty value for key 'list pauser'}\@ehd
- \else
- \let\skv@listpausertoks\skv@prova
- \fi
+ list pauser/\foreachlistpauser/
+ \edef\skv@prova{\unexpanded{#1}}%
+ \ifx\skv@prova\@empty
+ \skv@err{Invalid empty value for key 'list pauser'}\skv@ehd
+ \else
+ \let\skv@listpausertoks\skv@prova
\fi
;
% Remember outside the loop the holder values. Of course, this
@@ -768,25 +796,20 @@
% This default value of 'link' is required by \skv@foreach@filllist:
.exec code/\def\skv@foreach@link{\@nil};
link/\@nil/
- \ifskvindef\else
+ \edef\skv@prova{\unexpanded{#1}}%
+ \ifcase0%
+ \ifx\skv@prova\@empty 1\fi
+ \ifx\skv@prova\@nnil 1\fi\relax
\edef\skv@foreach@link{\unexpanded{#1}}%
\skvstripouterbraces{2}\skv@foreach@link
- \ifnum0>\numexpr0\ifx\skv@foreach@link\@empty-1\else
- \ifx\skv@foreach@link\@nnil-1\else+0\fi\fi\relax\relax
- \skv@err{The key 'link' doesn't accept empty/blank values}\@ehd
- \fi
\fi
;
grow/\@nil/
- \ifskvindef\else
- \edef\skv@prova{\unexpanded{#1}}%
- \ifx\skv@prova\@nnil
- \skv@err{Value required for key 'grow'}\@ehd
- \else
- \skvcsedef{skv@foreach@grow#1}{00}
- \edef\skv@prova{\skvifstrcmpTF{#1}{left}{right}{left}}%
- \skvcsedef{skv@foreach@grow\skv@prova}{01}%
- \fi
+ \edef\skv@prova{\unexpanded{#1}}%
+ \ifx\skv@prova\@nnil\else
+ \skvcsedef{skv@foreach@grow#1}{00}
+ \edef\skv@prova{\skvifstrcmpTF{#1}{left}{right}{left}}%
+ \skvcsedef{skv@foreach@grow\skv@prova}{01}%
\fi
/left,right
;
@@ -795,17 +818,13 @@
\def\skv@foreach@growright{01}
;
grow left/true/
- \ifskvindef\else
- \edef\skv@foreach@growleft{0\skvifstrcmpTF{true}{#1}01}
- \edef\skv@foreach@growright{0\skvifstrcmpTF{true}{#1}10}
- \fi
+ \edef\skv@foreach@growleft{0\skvifstrcmpTF{true}{#1}01}
+ \edef\skv@foreach@growright{0\skvifstrcmpTF{true}{#1}10}
/true,false
;
grow right/true/
- \ifskvindef\else
- \edef\skv@foreach@growright{0\skvifstrcmpTF{true}{#1}01}
- \edef\skv@foreach@growleft{0\skvifstrcmpTF{true}{#1}10}
- \fi
+ \edef\skv@foreach@growright{0\skvifstrcmpTF{true}{#1}01}
+ \edef\skv@foreach@growleft{0\skvifstrcmpTF{true}{#1}10}
/true,false
;
% Keep the decimals in rounded numbers or dimensions when list is
@@ -829,17 +848,17 @@
\edef\skv@foreach@expandlistbeforefill{0\skvifstrcmpTF{true}{#1}01}
/true,false
;
- expand list once,*,list is a macro,macro list/true/
+ expand list once,x1,list is a macro,macro list/true/
\edef\skv@foreach@expandlistonce{0\skvifstrcmpTF{true}{#1}01}%
/true,false
;
- expand list twice/true/
+ expand list twice,x2/true/
\edef\skv@foreach@expandlisttwice{0\skvifstrcmpTF{true}{#1}01}%
/true,false
;
% Don't use 'expand' for this key, to avoid confusing it with
% the 'expand' for holder macros:
- expand list,fully expand list,expand list fully/true/
+ expand list,fully expand list,expand list fully,xx/true/
\edef\skv@foreach@expandlistfully{0\skvifstrcmpTF{true}{#1}01}%
/true,false
;
@@ -847,38 +866,22 @@
\edef\skv@foreach@reverselist{0\skvifstrcmpTF{true}{#1}01}
/true,false
;
- reverse list,reverse,reflect/true/
- \edef\skv@foreach@reverselist{0\skvifstrcmpTF{true}{#1}01}
- /true,false
- ;
}
-% The following keys don't need a default value:
-%
-% link,evaluate,*evaluate,evaluate num,*evaluate num,
-% evaluate dim,*evaluate dim,expand,*expand,count in,*count in,
-% loop stopper,process up to,grow
-%
-\skvinitializeqkeys{skeyval/foreach}{%
- parser,
- subparser,
- callback terminator,
- process up to,
- process empty list=false,
- item counter,
- list breaker,
- list pauser,
- recover holder values=false,
- grow left=false,
- grow right=false,
- keep decimals=true,
- keep high decimals=false,
- inherit=false,
- expand before fill=false,
- reverse list=false,
- expand list once=false,
- expand list twice=false,
- expand list fully=false,
+% The following keys don't need presetting. The user must supply
+% values when they are called. In internal loops, their values will
+% have to be revised from those of the outer loop.
+%
+% link,evaluate,,evaluate num,evaluate dim,expand,count in,
+% process up to,grow
+%
+\quickkeys.preset{skeyval/foreach}{%
+ parser,subparser,loop stopper,callback terminator,process up to,
+ process empty list=false,item counter,list breaker,list pauser,
+ recover holder values=false,grow left=false,grow right=false,
+ keep decimals=true,keep high decimals=false,inherit=false,
+ expand before fill=false,reverse list=false,expand list once=false,
+ expand list twice=false,expand list fully=false,
}
\skvnewdef*\skv@foreach@kvlist{}
@@ -926,36 +929,36 @@
\edef\skv@provb{\skvtrimspace{##2}}%
\edef\skv@provc{\skvtrimspace{##3}}%
\ifx\skv@prova\@empty
- \skv@err{Value of key 'evaluate' has no holder macro}\@ehd
+ \skv@err{Value of key 'evaluate' has no holder macro}\skv@ehd
\else
\expandafter\skvifescapedTF\expandafter{\skv@prova}{%
\expandafter\skvifntypeTF\expandafter{\skv@prova}{}{%
\skv@err{Value of key 'evaluate': more than 1
\MessageBreak token \skvoxdetok\skv@prova.
- \MessageBreak I can't find holder macro}\@ehd
+ \MessageBreak I can't find holder macro}\skv@ehd
}%
}{%
\skv@err{Value of key 'evaluate':
- \MessageBreak holder macro \skvoxdetok\skv@prova not escaped}\@ehd
+ \MessageBreak holder macro \skvoxdetok\skv@prova not escaped}\skv@ehd
}%
\fi
\ifx\skv@provb\@empty
- \skv@err{Value of key 'evaluate' has no child macro}\@ehd
+ \skv@err{Value of key 'evaluate' has no child macro}\skv@ehd
\else
\expandafter\skvifescapedTF\expandafter{\skv@provb}{%
\expandafter\skvifntypeTF\expandafter{\skv@provb}{}{%
\skv@err{Value of key 'evaluate': more than 1
\MessageBreak token \skvoxdetok\skv@provb.
- \MessageBreak I can't find child macro}\@ehd
+ \MessageBreak I can't find child macro}\skv@ehd
}%
}{%
\skv@err{Value of key 'evaluate':
- \MessageBreak child \skvoxdetok\skv@provb not escaped}\@ehd
+ \MessageBreak child \skvoxdetok\skv@provb not escaped}\skv@ehd
}%
\fi
\ifx\skv@provc\@empty
\skv@err{Value of key 'evaluate' has no formula or
- \MessageBreak holder macro to be expanded}\@ehd
+ \MessageBreak holder macro to be expanded}\skv@ehd
\fi
\skv@tempxifin{\pgfmathparse}{##3}{%
\def\skv@tempc####1\pgfmathparse####2\skv@nil{%
@@ -963,7 +966,7 @@
\skv@foreach@swatrue
\else
\skv@err{Invalid token \detokenize{####1}
- \MessageBreak before \string\pgfmathparse}\@ehd
+ \MessageBreak before \string\pgfmathparse}\skv@ehd
\fi
}%
\skv@tempc##3\skv@nil
@@ -986,7 +989,7 @@
\skv@tempa#1\skv@nil
}{%
\skv@err{Value of key 'evaluate':
- \MessageBreak there is 'using', but no 'as'}\@ehd
+ \MessageBreak there is 'using', but no 'as'}\skv@ehd
}%
}{%
% No formula given. Maybe the key is 'expand' or still 'evaluate'
@@ -995,10 +998,10 @@
\skv@tempxifin{as}{#1}{%
\def\skv@tempb##1as##2##3\skv@nil{%
\ifx\@nnil##1\@nnil
- \skv@err{Value of key 'evaluate' has no holder macro}\@ehd
+ \skv@err{Value of key 'evaluate' has no holder macro}\skv@ehd
\else
\ifx\@nnil##2%
- \skv@err{Value of key 'evaluate' has no child macro}\@ehd
+ \skv@err{Value of key 'evaluate' has no child macro}\skv@ehd
\else
\skv@tempa##1as##2using##1\skv@nil
\fi
@@ -1008,7 +1011,7 @@
}{%
% No 'as' or 'using': #1 should be only the holder macro:
\ifx\@nnil#1\@nnil
- \skv@err{Value of key 'evaluate' has no holder macro}\@ehd
+ \skv@err{Value of key 'evaluate' has no holder macro}\skv@ehd
\else
\skvifntypeTF{#1}{%
% Expand the holder macro:
@@ -1016,7 +1019,7 @@
}{%
\skv@err{Value of key 'evaluate': more than 1
\MessageBreak token '\detokenize{#1}'.
- \MessageBreak I can't find holder macro}\@ehd
+ \MessageBreak I can't find holder macro}\skv@ehd
}%
\fi
}%
@@ -1047,7 +1050,7 @@
\skvrobustdef*\skv@foreach@parsepgfmathparse#1{%
\begingroup
\ifdefined\pgfmathparse\else
- \skv@err{No \string\pgfmathparse; 'pgfmath' module not loaded}\@ehd
+ \skv@err{No \string\pgfmathparse; 'pgfmath' module not loaded}\skv@ehd
\fi
\def\skv@tempxifin##1##2{%
\skvxifinTF{\detokenize{##1}}{\detokenize{##2}}%
@@ -1058,36 +1061,36 @@
\edef\skv@provb{\skvtrimspace{##2}}%
\edef\skv@provc{\skvtrimspace{##3}}%
\ifx\skv@prova\@empty
- \skv@err{Value of key 'pgfmath parse' has no holder macro}\@ehd
+ \skv@err{Value of key 'pgfmath parse' has no holder macro}\skv@ehd
\else
\expandafter\skvifescapedTF\expandafter{\skv@prova}{%
\expandafter\skvifntypeTF\expandafter{\skv@prova}{}{%
\skv@err{Value of key 'pgfmath parse': more than 1
\MessageBreak token \skvoxdetok\skv@prova.
- \MessageBreak I can't find holder macro}\@ehd
+ \MessageBreak I can't find holder macro}\skv@ehd
}%
}{%
\skv@err{Value of key 'pgfmath parse':
- \MessageBreak holder macro \skvoxdetok\skv@prova not escaped}\@ehd
+ \MessageBreak holder macro \skvoxdetok\skv@prova not escaped}\skv@ehd
}%
\fi
\ifx\skv@provb\@empty
- \skv@err{Value of key 'pgfmath parse' has no child macro}\@ehd
+ \skv@err{Value of key 'pgfmath parse' has no child macro}\skv@ehd
\else
\expandafter\skvifescapedTF\expandafter{\skv@provb}{%
\expandafter\skvifntypeTF\expandafter{\skv@provb}{}{%
\skv@err{Value of key 'pgfmath parse': more than 1
\MessageBreak token \skvoxdetok\skv@provb.
- \MessageBreak I can't find child macro}\@ehd
+ \MessageBreak I can't find child macro}\skv@ehd
}%
}{%
\skv@err{Value of key 'pgfmath parse':
- \MessageBreak child \skvoxdetok\skv@provb not escaped}\@ehd
+ \MessageBreak child \skvoxdetok\skv@provb not escaped}\skv@ehd
}%
\fi
\ifx\skv@provc\@empty
\skv@err{Value of key 'pgfmath parse' has no formula or
- \MessageBreak holder macro to be expanded}\@ehd
+ \MessageBreak holder macro to be expanded}\skv@ehd
\fi
\skv@tempxifin{\pgfmathparse}{##3}{%
\def\skv@tempc####1\pgfmathparse####2\skv@nil{%
@@ -1095,18 +1098,18 @@
\skv@foreach@swatrue
\else
\skv@err{Invalid token \detokenize{####1}
- \MessageBreak before \string\pgfmathparse}\@ehd
+ \MessageBreak before \string\pgfmathparse}\skv@ehd
\fi
}%
\expandafter\skv@tempc\skv@provc\skv@nil
}{%
\skv@tempxifin{\numexpr}{##3}{%
\skv@err{Value of key 'pgfmath parse':
- \MessageBreak\noexpand\numexpr not allowed}\@ehd
+ \MessageBreak\noexpand\numexpr not allowed}\skv@ehd
}{%
\skv@tempxifin{\dimexpr}{##3}{%
\skv@err{Value of key 'pgfmath parse':
- \MessageBreak\noexpand\dimexpr not allowed}\@ehd
+ \MessageBreak\noexpand\dimexpr not allowed}\skv@ehd
}{%
\skv@foreach@swatrue
\edef\skv@provc{\noexpand\pgfmathparse{\skvexpandonce\skv@provc}}%
@@ -1120,16 +1123,16 @@
\skv@tempa#1\skv@nil
}{%
\skv@err{Value of key 'pgfmath parse':
- \MessageBreak there is 'using', but no 'as'}\@ehd
+ \MessageBreak there is 'using', but no 'as'}\skv@ehd
}%
}{%
\skv@tempxifin{as}{#1}{%
\def\skv@tempb##1as##2##3\skv@nil{%
\ifx\@nnil##1\@nnil
- \skv@err{Value of key 'pgfmath parse' has no holder macro}\@ehd
+ \skv@err{Value of key 'pgfmath parse' has no holder macro}\skv@ehd
\else
\ifx\@nnil##2%
- \skv@err{Value of key 'pgfmath parse' has no child macro}\@ehd
+ \skv@err{Value of key 'pgfmath parse' has no child macro}\skv@ehd
\else
\skv@tempa##1as##2using##1\skv@nil
\fi
@@ -1139,7 +1142,7 @@
}{%
% No 'as' or 'using': #1 should be only the holder macro:
\ifx\@nnil#1\@nnil
- \skv@err{Value of key 'pgfmath parse' has no holder macro}\@ehd
+ \skv@err{Value of key 'pgfmath parse' has no holder macro}\skv@ehd
\else
\skvifntypeTF{#1}{%
% Evaluate the holder macro:
@@ -1147,7 +1150,7 @@
}{%
\skv@err{Value of key 'pgfmath parse': more than 1
\MessageBreak token '\detokenize{#1}'.
- \MessageBreak I can't find holder macro}\@ehd
+ \MessageBreak I can't find holder macro}\skv@ehd
}%
\fi
}%
@@ -1204,17 +1207,17 @@
\edef\skv@provc{\skvtrimspace{##3}}%
\edef\skv@provd{\skvtrimspace{##4}}%
\ifx\skv@prova\@empty
- \skv@err{Value of key 'count' has no counter macro}\@ehd
+ \skv@err{Value of key 'count' has no counter macro}\skv@ehd
\else
\expandafter\skvifescapedTF\expandafter{\skv@prova}{%
\expandafter\skvifntypeTF\expandafter{\skv@prova}{}{%
\skv@err{Value of key 'count in': more than 1
\MessageBreak token \skvoxdetok\skv@prova.
- \MessageBreak I can't find counter macro}\@ehd
+ \MessageBreak I can't find counter macro}\skv@ehd
}%
}{%
\skv@err{Value of key 'count':\MessageBreak
- counter macro \skvoxdetok\skv@prova not escaped}\@ehd
+ counter macro \skvoxdetok\skv@prova not escaped}\skv@ehd
}%
\fi
\ifx\skv@provd\@empty
@@ -1224,7 +1227,7 @@
\expandafter\let\skv@prova\skv@provd
}{%
\skv@err{Value of key 'count':\MessageBreak
- initial \skvoxdetok\skv@provd not an integer}\@ehd
+ initial \skvoxdetok\skv@provd not an integer}\skv@ehd
}%
\fi
\skv@foreach@swafalse
@@ -1240,11 +1243,11 @@
\expandafter\skvifntypeTF\expandafter{\skv@provb}{}{%
\skv@err{Value of key 'count in': more than 1
\MessageBreak token \skvoxdetok\skv@provb.
- \MessageBreak I can't find holder macro}\@ehd
+ \MessageBreak I can't find holder macro}\skv@ehd
}%
}{%
\skv@err{Value of key 'count':\MessageBreak
- holder macro \skvoxdetok\skv@provb not escaped}\@ehd
+ holder macro \skvoxdetok\skv@provb not escaped}\skv@ehd
}%
\skv@foreach@swatrue
% \skv@tester is the second argument of \skv@foreach@maketester.
@@ -1259,7 +1262,7 @@
\skv@tempa#1\skv@nil
}{%
\skv@err{Value of key 'count':
- \MessageBreak there is 'satisfying', but no 'all'}\@ehd
+ \MessageBreak there is 'satisfying', but no 'all'}\skv@ehd
}%
}{%
\skv@tempxifin{all}{#1}{%
@@ -1267,14 +1270,14 @@
}{%
% No 'all' or 'satisfying': #1 should be only the counter macro:
\ifx\@nnil#1\@nnil
- \skv@err{Value of key 'count' has no counter macro}\@ehd
+ \skv@err{Value of key 'count' has no counter macro}\skv@ehd
\else
\skvifntypeTF{#1}{%
\skv@tempa#1all satisfying\skv@nil
}{%
\skv@err{Value of key 'count in': more than 1
\MessageBreak token '\detokenize{#1}'.
- \MessageBreak I can't find counter macro}\@ehd
+ \MessageBreak I can't find counter macro}\skv@ehd
}%
\fi
}%
@@ -1308,7 +1311,7 @@
\skv@tempxifin{(}{#1}{%
\skv@err{Value of key 'remember': '(' found.
\MessageBreak I don't accept this PGF format.
- \MessageBreak remove the parenthesis '()'}\@ehd
+ \MessageBreak Remove the parenthesis '(<your input>)'}\skv@ehd
}{}%
\def\skv@tempa##1as##2initially##3\skv@nil{%
\edef\skv@prova{\skvtrimspace{##1}}%
@@ -1317,22 +1320,22 @@
\skv@foreach@swafalse
\ifx\skv@prova\@empty
\skv@err{Value of key 'remember' has no holder macro:
- \MessageBreak i.e., no macro that holds input}\@ehd
+ \MessageBreak i.e., no macro that holds input}\skv@ehd
\else
\expandafter\skvifescapedTF\expandafter{\skv@prova}{}{%
\skv@err{Value of key 'remember':
- \MessageBreak Holder macro \skvoxdetok\skv@prova not escaped}\@ehd
+ \MessageBreak Holder macro \skvoxdetok\skv@prova not escaped}\skv@ehd
}%
\fi
\ifx\skv@provb\@empty
\skv@err{Value of key 'remember' has no child macro;
- \MessageBreak i.e., no macro after 'as'}\@ehd
+ \MessageBreak i.e., no macro after 'as'}\skv@ehd
\else
\expandafter\skvifescapedTF\expandafter{\skv@provb}{%
\skv@foreach@swatrue
}{%
\skv@err{Value of key 'remember':
- \MessageBreak Child \skvoxdetok\skv@provb not escaped}\@ehd
+ \MessageBreak Child \skvoxdetok\skv@provb not escaped}\skv@ehd
}%
\fi
}%
@@ -1341,7 +1344,7 @@
\skv@tempa#1\skv@nil
}{%
\skv@err{Value of key 'remember':
- \MessageBreak There is 'initially', but no 'as'}\@ehd
+ \MessageBreak There is 'initially', but no 'as'}\skv@ehd
}%
}{%
\skv@tempxifin{as}{#1}{%
@@ -1350,6 +1353,7 @@
% No 'as' and 'initially':
\edef\skv@prova{\skvtrimspace{#1}}%
\ifx\skv@prova\@empty\else
+ % Go and raise error in \skv@tempa:
\skv@tempa#1as initially\skv@nil
\fi
}%
@@ -1391,7 +1395,7 @@
\skv@tempxifin{(}{#1}{%
\skv@err{Value of key 'recall': '(' found.
\MessageBreak I don't accept this PGF format.
- \MessageBreak remove the parenthesis '()'}\@ehd
+ \MessageBreak remove the parenthesis '()'}\skv@ehd
}{}%
\skv@foreach@swafalse
\def\skv@tempa##1initially##2\skv@nil{%
@@ -1399,7 +1403,7 @@
\edef\skv@provb{\skvtrimspace{##2}}%
\ifx\skv@prova\@empty
\skv@err{Value of key 'recall' has no holder macro:
- \MessageBreak i.e., no macro that holds input}\@ehd
+ \MessageBreak i.e., no macro that holds input}\skv@ehd
\else
\expandafter\skvifntypeTF\expandafter{\skv@prova}{%
\expandafter\skvifescapedTF\expandafter{\skv@prova}{%
@@ -1420,11 +1424,11 @@
}%
}{%
\skv@err{Value of key 'recall':
- \MessageBreak \detokenize{#1} is not escaped}\@ehd
+ \MessageBreak \detokenize{#1} is not escaped}\skv@ehd
}%
}{%
\skv@err{Value of key 'recall':
- \MessageBreak \detokenize{#1} is not one token}\@ehd
+ \MessageBreak \detokenize{#1} is not one token}\skv@ehd
}%
\fi
}%
@@ -1432,7 +1436,7 @@
\skv@err{Value of key 'recall': invalid 'as' found.
\MessageBreak This key doesn't expect 'as' since
\MessageBreak it automatically builds a retainer macro
- \MessageBreak of the form \<foreachlast><holder.name>}\@ehd
+ \MessageBreak of the form \<foreachlast><holder.name>}\skv@ehd
}{%
\skv@tempxifin{initially}{#1}{%
\skv@tempa#1\skv@nil
@@ -1486,60 +1490,48 @@
\endgroup
}%
\skvletmanytocmd{%
- \prependtobeginforeach\appendtobeginforeach\atbeginforeach
- \prependtoendforeach\appendtoendforeach\atendforeach
+ \prependtobeginforeach,\appendtobeginforeach,\atbeginforeach,
+ \prependtoendforeach,\appendtoendforeach,\atendforeach
}\skv@foreach@latehook
}
\skvrobustdef*\skv@foreach@pushstate{%
\skvsavestate\skv@foreach@stack{%
- \do\skv@foreach@seenstar
- \do\skv@foreach@parser\do\skv@foreach@subparser
- \do\skv@foreach@listisamacro
+ \do\skv@foreach@seenstar\do\skv@foreach@parser
+ \do\skv@foreach@subparser\do\skv@foreach@listisamacro
\do\skv@foreach@processupto\do\skv@foreach@processempty
- \do\skv@foreach@exittester
- \do\skv@foreach@grow\do\skv@foreach@growleft
- \do\skv@foreach@growright
+ \do\skv@foreach@exittester\do\skv@foreach@continuetester
+ \do\skv@foreach@grow\do\skv@foreach@growleft\do\skv@foreach@growright
\do\skv@foreach@terminator\do\skv@foreach@recoverholders
- \do\skv@foreach@callback
- \do\skv@foreach@auxcallback
- \do\skv@foreach@precallback
- \do\skv@foreach@afterprecallback
- \do\skv@foreach@postcallback
+ \do\skv@foreach@normalizelist\do\skv@foreach@callback
+ \do\skv@foreach@auxcallback\do\skv@foreach@precallback
+ \do\skv@foreach@afterprecallback\do\skv@foreach@postcallback
\do\skv@foreach@onlyinitially
\do\foreachlistremainder\do\skv@foreach@mainloop
- \do\skv@foreach@getnext\do\skv@foreach@getrm
+ \do\skv@foreach@getnext\do\skv@foreach@picknext\do\skv@foreach@getrm
\do\skv@foreach@do@a\do\skv@foreach@do@b
- \do\skv@foreach@paramlist
- \do\skv@foreach@holderlist
- \do\skv@foreach@userlist
- \do\skv@foreach@inherit
- \do\skv@foreach@keepdecimals
- \do\skv@foreach@keephighdecimals
- \do\skv@foreach@itemcounter
- \do\skv@foreach@link
+ % Macros '...lookahead...' need stacking in \foreachfox and when
+ % \newforeach is nested with \foreachfox:
+ \do\skv@foreach@lookahead@a\do\skv@foreach@lookahead@b
+ \do\skv@foreach@lookahead@c\do\skv@foreach@lookahead@d
+ \do\skv@foreach@paramlist\do\skv@foreach@holderlist
+ \do\skv@foreach@userlist\do\skv@foreach@inherit
+ \do\skv@foreach@keepdecimals\do\skv@foreach@keephighdecimals
+ \do\skv@foreach@itemcounter\do\skv@foreach@link
\do\skv@foreach@expandlistbeforefill\do\skv@foreach@expandlistonce
\do\skv@foreach@expandlisttwice\do\skv@foreach@expandlistfully
\do\skv@listbreakertoks\do\skv@listpausertoks
- \do\skv@foreach@reverselist
- \do\foreachcurrentitem
- \do\foreachnextitem
- \do\foreachitemcount
- \do\foreachprevitem
+ \do\skv@foreach@reverselist\do\foreachcurrentitem
+ \do\foreachnextitem\do\foreachitemcount\do\foreachprevitem
% The following commands are disabled on entry into the loop.
% Hence they need to be stacked here:
- \do\prependtobeginforeach
- \do\appendtobeginforeach
- \do\atbeginforeach
- \do\prependtoendforeach
- \do\appendtoendforeach
- \do\atendforeach
- }\foreachdepth
+ \do\prependtobeginforeach\do\appendtobeginforeach\do\atbeginforeach
+ \do\prependtoendforeach\do\appendtoendforeach\do\atendforeach
+ }\foreachnestdepth
}
\skvrobustdef*\skv@foreach@popstate{%
- \skvrestorestate\skv@foreach@stack\foreachdepth
+ \skvrestorestate\skv@foreach@stack\foreachnestdepth
}
-\skvnewdef*\foreachnestdepth{\foreachdepth}
\skvnewlet\skv@foreach@nil\relax
\skvnewdef*\skv@foreach@nnil{\skv@foreach@nil}
\skvrobustdef*\newforeach{\skv@testst\skv@newforeach@beginprescan}
@@ -1560,11 +1552,11 @@
}{%
\skvifnextchar i{%
\endgroup
- \skv@err{\string\newforeach: no holder macro seen}\@ehd
+ \skv@err{\string\newforeach: no holder macro seen}\skv@ehd
}{%
\skvifnextchar\skv@orig@bgroup{%
\endgroup
- \skv@err{\string\newforeach: no holder macro seen}\@ehd
+ \skv@err{\string\newforeach: no holder macro seen}\skv@ehd
}{%
\skv@foreach@collectholders
}%
@@ -1591,7 +1583,7 @@
}
\skvrobustdef*\skv@foreach@endprescan#1[#2]{%
\skvifblankTF{#1}{%
- \skv@err{\string\newforeach: no holder macros seen}\@ehd
+ \skv@err{\string\newforeach: no holder macros seen}\skv@ehd
}{%
\skv@foreach@scanarg[#2]#1%
}%
@@ -1602,18 +1594,17 @@
\skv@foreach@latehookerr
% \foreachitemcount must be a macro, not a counter, because it is stacked:
\def\foreachitemcount{0}%
- % Don't confuse item counters of various depths:
- \skvundef\skv@foreach@itemcounter
- \skvundef\skv@foreach@processupto
- \def\skv@foreach@callback{}%
- \def\skv@foreach@auxcallback{}%
- \def\skv@foreach@precallback{}%
- \def\skv@foreach@afterprecallback{}%
- \def\skv@foreach@postcallback{}%
- \def\skv@foreach@onlyinitially{}%
+ % Don't confuse macros of various depths; reset them here:
+ \def\do##1{\def##1{}}%
+ \do\skv@foreach@itemcounter\do\skv@foreach@processupto
+ \do\skv@foreach@callback\do\skv@foreach@auxcallback
+ \do\skv@foreach@precallback\do\skv@foreach@afterprecallback
+ \do\skv@foreach@postcallback\do\skv@foreach@onlyinitially
% The keys have to be set here, to determine if the list is a macro, etc.
% Since \skv@foreach@precallback are initialized in each nest, the
- % keys have to be reset here.
+ % keys have to be reset here. Reset all keys: they might have been
+ % fixed by the outer loop and the inner loop might assume the default
+ % values of the keys are those being used.
\skv@foreach@setkeys{#1}%
% We've set the keys; let's overrule \skv@foreach@expandlistonce if
% we had seen a star suffix. Don't overrule \skv@foreach@expandlisttwice
@@ -1622,9 +1613,10 @@
\def\skv@foreach@expandlistonce{00}%
\fi
\ifcase0%
- \if\skv@foreach@expandlistonce0\else
- \if\skv@foreach@expandlisttwice0\else
- \if\skv@foreach@expandlistfully0\else 1\fi\fi\fi\relax
+ % Take only one case:
+ \if\skv@foreach@expandlistonce\else
+ \if\skv@foreach@expandlisttwice\else
+ \if\skv@foreach@expandlistfully\else 1\fi\fi\fi\relax
\def\skv@foreach@listisamacro{00}%
\else
\def\skv@foreach@listisamacro{01}%
@@ -1647,7 +1639,7 @@
\skvifescapedTF{#1}{%
\skv@err{Token '\noexpand#1' cannot be a subparser;
\MessageBreak it seems to be a holder macro. I expected
- \MessageBreak the subparser to be the token here.}\@ehd
+ \MessageBreak the subparser to be the token here.}\skv@ehd
}{%
\edef\skv@prova{\skvtrimspace{#1}}%
\let\elt\skvexpandonce
@@ -1662,6 +1654,7 @@
\MessageBreak I have used '\elt\skv@prova', but please submit
\MessageBreak '\elt\skv@prova' as the value of the key
'subparser'
+ \MessageBreak so that I can stop giving this warning.
}%
\fi
\let\skv@foreach@subparser\skv@prova
@@ -1671,7 +1664,7 @@
\else
\skvifescapedTF{#1}{}{%
\skv@err{Token '\noexpand#1' is not escaped
- \MessageBreak and can't be a holder macro}\@ehd
+ \MessageBreak and can't be a holder macro}\skv@ehd
}%
\fi
\advance\skv@cnta\@ne
@@ -1687,13 +1680,13 @@
\skvifstrcmpTF{#1#2}{in}{%
\skv@foreach@scanarg@d
}{%
- \skv@err{I have seen 'i' but no expected 'in'}\@ehd
+ \skv@err{I have seen 'i' but no expected 'in'}\skv@ehd
}%
}
\skvrobustdef*\skv@foreach@scanarg@d{%
\ifx\skv@foreach@holderlist\@empty
\skv@err{No item holder macros before 'in'
- \MessageBreak or before left brace}\@ehd
+ \MessageBreak or before left brace}\skv@ehd
\fi
\skvifnextchar\skv@orig@bgroup{%
\skv@foreach@scanarg@e
@@ -1707,7 +1700,7 @@
\noexpand\newforeach or key 'expand list once', etc.,
\MessageBreak is missing.}%
}{%
- \let\skv@tempehd\@ehd
+ \let\skv@tempehd\skv@ehd
}%
\skv@err{I expected a left brace for beginning of list,
\MessageBreak since you haven't told me that your
@@ -1734,7 +1727,7 @@
\skvifnextchar\skv@orig@bgroup
\skv@foreach@scanarg@h\skv@foreach@scanarg@g
}{%
- \skv@err{I have seen 'd' but no the expected 'do'}\@ehd
+ \skv@err{I have seen 'd' but no the expected 'do'}\skv@ehd
}%
}
% We've exhausted all options for grabbing the callback, so now
@@ -1775,7 +1768,7 @@
\skv@prova
}%
% In case callback terminator is currently active, rescan it.
- \skv@rescan\skv@foreach@terminator
+ \skvrescan\skv@foreach@terminator
\expandafter\skv@prova\expandafter{\skv@foreach@terminator}%
}
% #1: callback
@@ -1812,16 +1805,19 @@
{#2}%
}%
% Initial code, if any:
- \skvcsuse{skv@foreach@atbeginhook@\skvrom\foreachdepth}%
+ \skvcsuse{skv@foreach@atbeginhook@\skvrom\foreachnestdepth}%
\skvifdefTF\foreachprevitem{}{\def\foreachprevitem{}}%
- \expandafter\skv@foreach@normalize\expandafter
- [\skv@foreach@parser]\skv@foreach@userlist
- \expandafter\skv@foreach@normalize\expandafter
- [\skv@foreach@subparser]\skv@foreach@userlist
+ \expandafter\skv@foreach@normalize\expandafter[\skv@foreach@parser]%
+ \skv@foreach@userlist
+ \expandafter\skv@foreach@normalize\expandafter[\skv@foreach@subparser]%
+ \skv@foreach@userlist
+ \ifnum\foreachnestdepth=\skvz@
+ \breakallforeachloopsfalse
+ \fi
\skvbreakloopfalse
\foreachlastitemfalse
\def\skv@foreach@lookahead@a##1{%
- \def\skv@foreach@continue{##1.}%
+ \def\skv@foreach@picknext{##1.}%
\futurelet\skv@foreach@next\skv@foreach@lookahead@b
}%
\def\skv@foreach@lookahead@b{%
@@ -1831,12 +1827,12 @@
\ifx\skv@foreach@next(%
\expandafter\expandafter\expandafter\skv@foreach@lookahead@d
\else
- \expandafter\expandafter\expandafter\skv@foreach@continue
+ \expandafter\expandafter\expandafter\skv@foreach@picknext
\fi
\fi
}%
- \def\skv@foreach@lookahead@c[##1]{\skv@foreach@continue[{##1}]}%
- \def\skv@foreach@lookahead@d(##1){\skv@foreach@continue({##1})}%
+ \def\skv@foreach@lookahead@c[##1]{\skv@foreach@picknext[{##1}]}%
+ \def\skv@foreach@lookahead@d(##1){\skv@foreach@picknext({##1})}%
\def\skv@foreach@mainloop##1{%
\def\skv@foreach@getnext####1##1####2\skv@foreach@stop{%
\edef\foreachnextitem{\skvexpandonce{\@gobble####1}}%
@@ -1874,21 +1870,17 @@
}%
\def\skv@foreach@do@b####1{%
\edef\foreachitemcount{\the\numexpr\foreachitemcount+1}%
- \ifcase0%
- \ifx\skv@foreach@itemcounter\@undefined 1\fi
- \ifx\skv@foreach@itemcounter\@empty 1\fi
- \ifx\skv@foreach@itemcounter\@nnil 1\fi\relax
+ \ifx\skv@foreach@itemcounter\@empty\else
\expandafter\let\skv@foreach@itemcounter\foreachitemcount
\fi
\skv@foreach@lookahead@a\skv@foreach@getnext####1\skv@foreach@stop
- % In case the user decides to continue after \listpauser:
+ % If the user decides to continue after \foreachlistpauser is picked up,
+ % don't use \foreachlistpauser as an item:
\skvifxTF\foreachcurrentitem\skv@listpausertoks{}{%
- \expandafter\skv@foreach@callback\expandafter{\foreachcurrentitem}%
+ \skvexpbracenext\skv@foreach@callback\foreachcurrentitem
+ \let\foreachprevitem\foreachcurrentitem
}%
- \let\foreachprevitem\foreachcurrentitem
- \ifcase0%
- \ifx\skv@foreach@processupto\@undefined 1\fi
- \ifx\skv@foreach@processupto\@nnil 1\fi\relax
+ \ifx\skv@foreach@processupto\@empty\else
\ifnum\foreachitemcount<\skv@foreach@processupto\relax\else
\skvbreakloop
\fi
@@ -1900,7 +1892,9 @@
}%
}%
\def\skv@foreach@getrm####1{%
- \skvbreakloopfalse
+ \ifbreakallforeachloops\else
+ \skvbreakloopfalse
+ \fi
\foreachlastitemfalse
\def\skv@prova########1\skv@foreach@nil##1{%
\edef\foreachlistremainder{\unexpanded{########1}}%
@@ -1909,7 +1903,9 @@
\skv@prova####1%
}%
\skvifxTF\skv@foreach@userlist\@empty{%
- \if\skv@foreach@processempty\skv@foreach@callback{}\fi
+ \if\skv@foreach@processempty\skvafterfi
+ \skv@foreach@callback{}%
+ \fi
}{%
\expandafter\skv@foreach@filllist\expandafter
{\skv@foreach@parser}\skv@foreach@userlist
@@ -1924,16 +1920,16 @@
\skv@foreach@makeprecode{#1}%
\if\skv@foreach@recoverholders\else
\expandafter\skvsavestate\expandafter\skv@foreach@holderstate
- \expandafter{\skv@foreach@holderlist}\skv@foreach@sisterdepth
+ \expandafter{\skv@foreach@holderlist}\skv@foreach@holderdepth
\fi
\skv@foreach@makeauxcallback{#3}%
\skvexpandbracenext\skv@foreach@mainloop\skv@foreach@parser
- \skvcsuse{skv@foreach@atendhook@\skvrom\foreachdepth}%
+ \skvcsuse{skv@foreach@atendhook@\skvrom\foreachnestdepth}%
\if\skv@foreach@recoverholders\else
- \skvrestorestate\skv@foreach@holderstate\skv@foreach@sisterdepth
+ \skvrestorestate\skv@foreach@holderstate\skv@foreach@holderdepth
\fi
\skv@foreach@popstate
- \ifnum\foreachdepth=\skvz@
+ \ifnum\foreachnestdepth=\skvz@
\def\skv@warnsubparser{0}%
\fi
}
@@ -1957,7 +1953,7 @@
\ifx\skv@prova\skv@foreach@subparser
\ifnum\skv@cnta=\skvz@
\skv@err{Subparser '\skvoxdetok\skv@foreach@subparser' can't come
- first in the list\MessageBreak of holder macros}\@ehd
+ first in the list\MessageBreak of holder macros}\skv@ehd
\else
% Eg, if subparser is slash (/), \skv@foreach@paramlist will have
% the syntax: ##1/##2/...:
@@ -2010,6 +2006,20 @@
\skvcmdexit\skv@foreach@precallback
}%
}
+% Example (*):
+%
+% This example demonstrates why \skv@foreach@continuetester must be
+% located delicately, at where it is currently.
+%
+% \def\ditem{D}
+% \newforeach [
+% continue=\ifx\x\ditem\fi,remember=\x as \rx initially A
+% ] \x in {
+% B,(C1),D,E,[F1],G,H
+% }{%
+% $\overrightarrow{\rx\x}$\ifforeachlastitem.\else,\space\fi
+% }
+%
% #1: callback
\skvrobustdef*\skv@foreach@makeauxcallback#1{%
\begingroup
@@ -2022,25 +2032,37 @@
% Add extra subparsers in case some items aren't subparser-complete:
\edef\skv@tempa{\skv@generatesubparser{1}}%
\let\foreacheov\relax
- \let\\\noexpand
+ \let\do\noexpand
\skvexpanded{\endgroup
% Define auxiliary callback:
- \def\\\skv@foreach@auxcallback\skv@foreach@paramlist\foreacheov{%
+ \def\do\skv@foreach@auxcallback\skv@foreach@paramlist\foreacheov{%
% Holder macro assignments:
\skvexpandonce\skv@foreach@precallback
% User tests/tasks, eg, if requested from 'evaluate' key:
\skvexpandonce\skv@foreach@afterprecallback
- \\\ifnum\\\foreachitemcount=\@ne
- \\\skv@foreach@onlyinitially
- \\\fi
- \unexpanded{#1}%
- % User tests/tasks, eg, if requested from the keys 'remember',
- % 'exit when', etc:
- \skvexpandonce\skv@foreach@postcallback
+ \do\ifnum\do\foreachitemcount=\@ne
+ \do\skv@foreach@onlyinitially
+ \do\fi
+ \ifx\skv@foreach@continuetester\@secondoftwo
+ \noexpand\skv@foreach@continuetester
+ \else
+ % Expose the parameter characters in \skv@foreach@continuetester:
+ \skvexpandonce\skv@foreach@continuetester
+ \fi
+ {%
+ \relax
+ }{%
+ % If the user wants to ignore the callback for some items, he can
+ % use the key 'continue=<condition>':
+ \unexpanded{#1}%
+ % User tests/tasks, eg, if requested from the keys 'remember',
+ % 'exit when', etc:
+ \skvexpandonce\skv@foreach@postcallback
+ }%
}%
% Define the real callback:
- \def\\\skv@foreach@callback####1{%
- \\\skv@foreach@auxcallback####1\skvxonce\skv@tempa\foreacheov
+ \def\do\skv@foreach@callback####1{%
+ \do\skv@foreach@auxcallback####1\skvxonce\skv@tempa\foreacheov
}%
}%
}
@@ -2132,7 +2154,7 @@
\skvifdefTF\skv@foreach@link{%
\skvifxFT\skv@foreach@link\@nnil
}{%
- \skv@err{List auto-completion: 'link' is undefined}\@ehd
+ \skv@err{List auto-completion: 'link' is undefined}\skv@ehd
}%
}%
\skvexpanded{%
@@ -2158,8 +2180,7 @@
\skv@foreach@normalize[#1]\skv@foreach@filledlist
}{%
\edef\skv@foreach@filledlist{%
- \skvaddlist{#1}\skv@foreach@filledlist
- \skvtrimspace{##1}%
+ \skvaddlist{#1}\skv@foreach@filledlist\skvtrimspace{##1}%
}%
}%
}%
@@ -2168,10 +2189,10 @@
% \skv@foreach@filllist@b{<parser>}{<list>}
\skvrobustdef*\skv@foreach@filllist@b#1#2{%
\skvxiffound{\relax...}\in{\relax\detokenize{#2}}\then
- \skv@err{I can't find lower limit before '...'}\@ehd
+ \skv@err{I can't find lower limit before '...'}\skv@ehd
\else
\skvxiffound{\relax\detokenize{#1}...}\in{\relax\detokenize{#2}}\then
- \skv@err{I can't find lower limit before '...'}\@ehd
+ \skv@err{I can't find lower limit before '...'}\skv@ehd
\fi
\fi
% \newforeach format is '<parser>...<parser>':
@@ -2180,7 +2201,7 @@
\def\skv@prova##1#1##2#1...#1##3#1##4#1##5\skv@nil{%
\skvifblankTF{##3}{%
\skv@err{I can't find upper limit number or dimension,
- \MessageBreak i.e., after symbool '...'}\@ehd
+ \MessageBreak i.e., after symbool '...'}\skv@ehd
}{%
% \skv@foreach@filllist@a may be reentered. Hence accumulate
% filled list:
@@ -2198,7 +2219,7 @@
\expandafter\skv@prova\skv@tempa#1#1\skv@nil
}{%
% Not \newforeach format: try PGF's \foreach format:
- \skv@foreach@trypgfformat{#1}{#2}%
+ \skv@foreach@trypgflikeformat{#1}{#2}%
}%
}
@@ -2247,7 +2268,7 @@
\MessageBreak or both directions are 'true'.}
{Try one of the keys 'grow=left or right',
\MessageBreak 'grow left=true or false',
- 'grow right=true or false'}\@ehd
+ 'grow right=true or false'}\skv@ehd
\fi
\begingroup
\def\skv@prova##1{%
@@ -2260,7 +2281,7 @@
\ifskv@foreach@swa\else
\edef\skv@provb{\ifx\@nnil#2\@nnil\else\unexpanded{#2}, \fi}%
\skv@err{No link '##1' in one of
- '\detokenize\expandafter{\skv@provb#3, #4}'}\@ehd
+ '\detokenize\expandafter{\skv@provb#3, #4}'}\skv@ehd
\fi
\def\skv@prova####1##1####2\skv@nil{%
\if\skv@foreach@growright
@@ -2269,9 +2290,9 @@
\edef\skv@prova{\skvtrimspace{##1####2}}%
\fi
\def\do########1{{\skvtrimspace{########1}}}%
- % \skv@foreach@trypgfformat@a<parser><guide><lower1><lower2><upper>
+ % \skv@foreach@trypgflikeformat@a<parser><guide><lower1><lower2><upper>
\skvexpanded{\endgroup
- \noexpand\skv@foreach@trypgfformat@a
+ \noexpand\skv@foreach@trypgflikeformat@a
{\unexpanded{#1}}{\skvexpandonce\skv@prova}\do{#2}\do{#3}\do{#4}%
}%
}%
@@ -2291,7 +2312,7 @@
% {A_1,B_1,..._1,E_1} : <guide> = _1
% {1--,4--,...--,16--} : <guide> = --
% {1pt,4pt,...pt,10pt} : <guide> = pt
-% {A_2pt,A_4pt,A_...pt,A_10pt} : <guide> = A_, pt
+% {A_2pt,A_4pt,A_...pt,A_10pt} : <guide> = A_ and pt
%
% skeyval formats:
% {a^1,a^3,a^...,a^9} : no additional info. required
@@ -2308,14 +2329,14 @@
%
% The items prior to the last 2 items before '<guide>...' or before '...'
% are called 'before-the-last-2' (BL2). Collect in \skv@tempa BL2 items,
-% together with the rest of the list. Save in \skv@foreach@filledlist
-% the BL2 items.
+% together with the rest of the list. Save the BL2 items in
+% \skv@foreach@filledlist.
%
% Return \skv@foreach@filledlist and \skv@tempa.
%
\skvrobustdef*\skv@foreach@splitonguide#1#2{%
% First count all the elements before '<guide>,...'. We're already
- % sure that #2 contains '<guide>,...' or '...':
+ % sure that #2 contains '<guide><parser>...' or '...':
\begingroup
\skv@cnta\skvz@
\def\do##1#1{%
@@ -2350,7 +2371,7 @@
\else
\ifnum\skv@cnta=\skvz@
\skv@err{List <<\detokenize{#2}>>\MessageBreak
- contains symbol '...' but not a lowerbound}\@ehd
+ contains symbol '...' but not a lowerbound}\skv@ehd
\fi
\fi
\fi
@@ -2360,16 +2381,21 @@
}%
}
-% \skv@foreach@trypgfformat{<parser>}{<list>}
+% \skv@foreach@trypgflikeformat{<parser>}{<list>}
+%
+% When we say 'try PGF-like format', we don't actually mean the
+% PGF format with left and right guides, as in,
+%
+% {A_2pt,A_4pt,A_...pt,A_10pt} : <guide> = 'A_(left)' and 'pt(right)' (*)
%
-% When we say, 'try PGF format', we don't actually mean the PGF format with
-% left and right guides, but the syntax '<guide>...' (ie, having only the
-% left-hand-side or only the right-hand-side guide). For example,
+% but the syntax '<guide>...' (ie, having only the left-hand-side or only
+% the right-hand-side guide). For example,
%
% {A_2pt,A_4pt,A_...,A_10pt} or {1pt,4pt,...pt,10pt}
%
-% \skv@foreach@trypgfformat will auto-complete this list without
-% knowledge of the values of the keys 'link' and 'grow'.
+% \skv@foreach@trypgflikeformat will auto-complete this list without
+% knowledge of the values of the keys 'link' and 'grow'. The syntax at (*)
+% above isn't recognized by the auto-completion scheme of skeyval.
%
% skeyval formats:
%
@@ -2382,15 +2408,15 @@
%
% {A_2pt,A_4pt,A_...pt,A_10pt}
%
-% is illegal here, because the skeyval-for package uses the location
+% is illegal here, because the file skeyval-for.tex uses the location
% of the guide (left or right of ...) to determine the direction of growth.
%
-\skvrobustdef*\skv@foreach@trypgfformat#1#2{%
+\skvrobustdef*\skv@foreach@trypgflikeformat#1#2{%
\skv@foreach@splitonguide{#1}{#2}%
\def\skv@prova##1#1##2#1##3...##4#1##5#1##6#1##7\skv@nil{%
\skvifblankTF{##5}{%
\skv@err{I can't find upper limit number or dimension,
- \MessageBreak i.e., after symbool '...'}\@ehd
+ \MessageBreak i.e., after symbool '...'}\skv@ehd
}{%
% \skv@foreach@filllist@a may be reentered. Hence
\skviflacus{##1}\then\else
@@ -2403,12 +2429,12 @@
\skvifblankTF{##3}{%
\skvifblankTF{##4}{%
\skv@err{No direction of growth before and/or after
- \MessageBreak symbol '...'}\@ehd
+ \MessageBreak symbol '...'}\skv@ehd
}{%
\def\skv@foreach@growleft{00}%
\def\skv@foreach@growright{01}%
\skvexpanded{%
- \skv@foreach@trypgfformat@a
+ \skv@foreach@trypgflikeformat@a
{\unexpanded{#1}}\do{##4}\do{##1}\do{##2}\do{##5}%
}%
}%
@@ -2417,17 +2443,17 @@
\def\skv@foreach@growright{00}%
\def\skv@foreach@growleft{01}%
\skvexpanded{%
- \skv@foreach@trypgfformat@a
+ \skv@foreach@trypgflikeformat@a
{\unexpanded{#1}}\do{##3}\do{##1}\do{##2}\do{##5}%
}%
}{%
- \skv@err{Having both '\detokenize{##3 and ##4}' in an
+ \skv@err{Having both '\detokenize{'##3' and '##4'} in an
\MessageBreak ellipsis list is illegal in
- \MessageBreak\noexpand\newforeach and \noexpand\newforeach.
+ \MessageBreak\noexpand\newforeach and \noexpand\foreachfox.
\MessageBreak I know that PGF's \noexpand\foreach needs it,
\MessageBreak but I don't need it. I can
\MessageBreak auto-fill your list with information
- \MessageBreak on only one side.}\@ehd
+ \MessageBreak on only one side of <<...>>.}\skv@ehd
}%
}%
% In case the list is folded on ellipsis (...):
@@ -2437,7 +2463,8 @@
\expandafter\skv@prova\skv@tempa#1#1#1\skv@nil
}
%
-% \skv@foreach@trypgfformat@a{<parser>}{<guide>}{<lower1>}{<lower2>}{<upper>}
+% \skv@foreach@trypgflikeformat@a
+% {<parser>}{<guide>}{<lower1>}{<lower2>}{<upper>}
%
% 1. Use the <guide> to get the contant and variable parts of the
% elements.
@@ -2448,7 +2475,7 @@
% 4. Call the relevant macro to fill the list.
% 5. <lower1> has already been saved in \skv@foreach@filledlist.
%
-\skvrobustdef*\skv@foreach@trypgfformat@a#1#2#3#4#5{%
+\skvrobustdef*\skv@foreach@trypgflikeformat@a#1#2#3#4#5{%
\skv@foreach@swafalse
\skviflacus#3\then\else
\skvxifinTF{#2}{#3}{}\skv@foreach@swatrue
@@ -2459,7 +2486,7 @@
\skv@err{Guide token '\detokenize{#2}' not found in some
\MessageBreak of the elements: I can't complete
\MessageBreak the current list. This may be
- \MessageBreak due to wrong direction of growth}\@ehd
+ \MessageBreak due to wrong direction of growth}\skv@ehd
\fi
% Get from the left or right of 'link' (#2) the components that should be
% grown, without the link:
@@ -2516,7 +2543,7 @@
\skv@foreach@restoreguideandunit{#1}{#2}\skv@templist
\else
\skv@err{The tokens '\detokenize\expandafter{\skv@lowerlower#4, #5}'
- \MessageBreak aren't of the same type}\@ehd
+ \MessageBreak aren't of the same type}\skv@ehd
\fi
}{%
\skv@foreach@ifupperalpha{#4}{%
@@ -2541,7 +2568,7 @@
\skv@foreach@restoreguideandunit{#1}{#2}\skv@templist
\else
\skv@err{The tokens '\detokenize\expandafter{\skv@lowerlower#4, #5}'
- \MessageBreak aren't of the same type}\@ehd
+ \MessageBreak aren't of the same type}\skv@ehd
\fi
}{%
\skv@foreach@swatrue
@@ -2552,7 +2579,7 @@
\let\skv@foreach@origunit\skv@dimunit
\skvifdimensionable{#5}{}\skv@foreach@swafalse
\ifx\skv@foreach@origunit\skv@dimunit\else
- \skv@err{The units on \detokenize{'#4', '#5'} are different}\@ehd
+ \skv@err{The units on \detokenize{'#4', '#5'} are different}\skv@ehd
\fi
\ifskv@foreach@swa
\ifx\@nnil#3\@nnil
@@ -2571,7 +2598,7 @@
}\skv@templist
\skv@foreach@strippoint{#1}\skv@templist
% Attach the constant part to the elements of the completed list.
- % <lower1> was saved earlier in \skv@foreach@trypgfformat, and
+ % <lower1> was saved earlier in \skv@foreach@trypgflikeformat, and
% <lower2> and <upper> have been saved while filling the list.
% Always strip point and restore original unit here.
\skv@foreach@restoreguideandunit{#1}{#2}\skv@templist
@@ -2605,7 +2632,7 @@
'\detokenize\expandafter{\skv@lowerlower#4, #5}'
\MessageBreak are unparsable. I have given up on them.
\MessageBreak Did you miss something syntactic?
- \MessageBreak See manual for acceptable syntaxes}\@ehd
+ \MessageBreak See manual for acceptable syntaxes}\skv@ehd
\fi
\fi
}%
@@ -2666,13 +2693,13 @@
\ifdim#3\skv@foreach@unit>#2\skv@foreach@unit\relax
\skv@err{Step '\skv@foreach@step' is negative but upperbound
\MessageBreak '\detokenize{#3}' is greater than lowerbound
- '\detokenize{#2}'}\@ehd
+ '\detokenize{#2}'}\skv@ehd
\fi
\else
\ifdim#3\skv@foreach@unit<#2\skv@foreach@unit\relax
\skv@err{Step '\skv@foreach@step' is nonnegative but upperbound
\MessageBreak '\detokenize{#3}' is less than lowerbound
- '\detokenize{#2}'}\@ehd
+ '\detokenize{#2}'}\skv@ehd
\fi
\fi
% The bounds may have decimal places. So the calculation has to be
@@ -2711,7 +2738,7 @@
\edef\reserved@a{\if-\skv@foreach@step\else\skv@foreach@step\fi}%
\skvoifinteger\reserved@a{}{%
\skv@err{List is '\skv@type' type but\MessageBreak
- step '\skv@foreach@step' isn't an integer}\@ehd
+ step '\skv@foreach@step' isn't an integer}\skv@ehd
}%
\skv@foreach@addtolist{#1}{#2}#4%
\skvifstrcmpTF{#2}{#3}{}{%
diff --git a/Master/texmf-dist/tex/latex/skeyval/skeyval-ltxcmds.tex b/Master/texmf-dist/tex/latex/skeyval/skeyval-ltxcmds.tex
index 17b4c19c9d5..0235cf5bfb1 100644
--- a/Master/texmf-dist/tex/latex/skeyval/skeyval-ltxcmds.tex
+++ b/Master/texmf-dist/tex/latex/skeyval/skeyval-ltxcmds.tex
@@ -1,5 +1,5 @@
%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
-% This is file 'skeyval-ltxcmds.tex', version 1.1a, 2012/10/16. %
+% This is file 'skeyval-ltxcmds.tex', version 1.2, 2013/02/10. %
% %
% This package and accompanying files may be distributed and/or %
% modified under the conditions of the LaTeX Project Public License, %
@@ -23,7 +23,7 @@
% skeyval-pstkey.sty, skeyval-pstkey.tex, skeyval-testclass.cls, %
% and skeyval-testpkg.sty. %
% %
-% Copyright (c) 2010-2012 Ahmed Musa (amusa22@gmail.com). %
+% Copyright (c) 2010-2013 Ahmed Musa (amusa22@gmail.com). %
%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
\begingroup%
@@ -58,7 +58,7 @@
\csname skeyval-ltxcmds-loaded\endcsname
\expandafter\let\csname skeyval-ltxcmds-loaded\endcsname\endinput
-\message{skeyval-ltxcmds 2012/10/16 v1.1a skeyval TeX header (AM)}
+\message{skeyval-ltxcmds 2013/02/10 v1.2 skeyval LaTeX header (AM)}
\countdef\m@ne=22 \m@ne=-1
\def\wlog{\immediate\write\m@ne}
@@ -146,7 +146,6 @@
\xdef#1{\the\toks@}%
\endgroup
}
-
% In case we call \@latex@error, etc, without LaTeX:
\newwrite\@unused
\def\typeout#1{%
@@ -282,7 +281,6 @@ Type H <return> for immediate help%
}%
}
\def\@infonoline#1{\@latex@info{#1\@gobble}}
-
\errorcontextlines=\m@ne
\ifnum\inputlineno=\m@ne
\let\on@line\@empty
diff --git a/Master/texmf-dist/tex/latex/skeyval/skeyval-ltxpatch.sty b/Master/texmf-dist/tex/latex/skeyval/skeyval-ltxpatch.sty
index 82d624e3985..3bea153e722 100644
--- a/Master/texmf-dist/tex/latex/skeyval/skeyval-ltxpatch.sty
+++ b/Master/texmf-dist/tex/latex/skeyval/skeyval-ltxpatch.sty
@@ -1,5 +1,5 @@
%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
-% This is file 'skeyval-ltxpatch.sty', version 1.1a, 2012/10/16. %
+% This is file 'skeyval-ltxpatch.sty', version 1.2, 2013/02/10. %
% %
% The rationale for this package: the patch in 'xkvltxp' package isn't %
% strong enough. %
@@ -26,7 +26,7 @@
% skeyval-pstkey.sty, skeyval-pstkey.tex, skeyval-testclass.sty, %
% and skeyval-testpkg.sty. %
% %
-% Copyright (c) 2010-2012 Ahmed Musa (amusa22@gmail.com). %
+% Copyright (c) 2010-2013 Ahmed Musa (amusa22@gmail.com). %
%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
\begingroup
@@ -72,7 +72,7 @@
\NeedsTeXFormat{LaTeX2e}[2011/06/27]
\ProvidesPackage{skeyval-ltxpatch}
- [2012/10/16 v1.1a Patches for LaTeX2e kernel options processing (AM)]
+ [2013/02/10 v1.2 Patches for LaTeX2e kernel options processing (AM)]
\ifdefined\skvz@\else\newdimen\skvz@\fi
\def\@space{ }
diff --git a/Master/texmf-dist/tex/latex/skeyval/skeyval-pstkey.sty b/Master/texmf-dist/tex/latex/skeyval/skeyval-pstkey.sty
index 280338217ac..c3f458644e6 100644
--- a/Master/texmf-dist/tex/latex/skeyval/skeyval-pstkey.sty
+++ b/Master/texmf-dist/tex/latex/skeyval/skeyval-pstkey.sty
@@ -1,5 +1,5 @@
%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
-% This is file 'skeyval-pstkey.sty', version 1.1a, 2012/10/16. %
+% This is file 'skeyval-pstkey.sty', version 1.2, 2013/02/10. %
% %
% This package and accompanying files may be distributed and/or %
% modified under the conditions of the LaTeX Project Public License, %
@@ -23,7 +23,7 @@
% skeyval-pstkey.sty, skeyval-pstkey.tex, skeyval-testclass.cls, %
% and skeyval-testpkg.sty. %
% %
-% Copyright (c) 2010-2012 Ahmed Musa (amusa22@gmail.com). %
+% Copyright (c) 2010-2013 Ahmed Musa (amusa22@gmail.com). %
%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
\begingroup
@@ -69,7 +69,7 @@
\NeedsTeXFormat{LaTeX2e}[2011/06/27]
\ProvidesPackage{skeyval-pstkey}
- [2012/10/16 v1.1a LaTeX/package wrapper for skeyval-pstkey.tex (AM)]
+ [2013/02/10 v1.2 LaTeX/package wrapper for skeyval-pstkey.tex (AM)]
\expandafter\ifx\csname skeyval-pstkey-loaded\endcsname
\endinput\else
diff --git a/Master/texmf-dist/tex/latex/skeyval/skeyval-pstkey.tex b/Master/texmf-dist/tex/latex/skeyval/skeyval-pstkey.tex
index bc5952d0377..4e2dc1f9ad7 100644
--- a/Master/texmf-dist/tex/latex/skeyval/skeyval-pstkey.tex
+++ b/Master/texmf-dist/tex/latex/skeyval/skeyval-pstkey.tex
@@ -1,5 +1,5 @@
%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
-% This is file 'skeyval-pstkey.tex', version 1.1a, 2012/10/16. %
+% This is file 'skeyval-pstkey.tex', version 1.2, 2013/02/10. %
% %
% This package and accompanying files may be distributed and/or %
% modified under the conditions of the LaTeX Project Public License, %
@@ -23,7 +23,7 @@
% skeyval-pstkey.sty, skeyval-pstkey.tex, skeyval-testclass.cls, %
% and skeyval-testpkg.sty. %
% %
-% Copyright (c) 2010-2012 Ahmed Musa (amusa22@gmail.com). %
+% Copyright (c) 2010-2013 Ahmed Musa (amusa22@gmail.com). %
%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
\begingroup%
@@ -62,12 +62,12 @@
\def\skv@@afterelse#1\else#2\fi{\fi#1}
\ifx\ProvidesFile\@undefined\skv@@afterelse
- \message{File 'skeyval-pstkey.tex' 2012/10/16 v1.1a
+ \message{File 'skeyval-pstkey.tex' 2013/02/10 v1.2
PSTricks specialization of skeyval package (AM)}
\input skeyval-core
\else\skv@@afterfi
\ProvidesFile{skeyval-pstkey.tex}
- [2012/10/16 v1.1a PSTricks specialization of skeyval (AM)]
+ [2013/02/10 v1.2 PSTricks specialization of skeyval (AM)]
\@addtofilelist{skeyval-pstkey.tex}
\@ifpackageloaded{skeyval}{}{\RequirePackage{skeyval}}
\fi
diff --git a/Master/texmf-dist/tex/latex/skeyval/skeyval-view.sty b/Master/texmf-dist/tex/latex/skeyval/skeyval-view.sty
index 6e40b3d6611..4996acf58b3 100644
--- a/Master/texmf-dist/tex/latex/skeyval/skeyval-view.sty
+++ b/Master/texmf-dist/tex/latex/skeyval/skeyval-view.sty
@@ -1,5 +1,5 @@
%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
-% This is file 'skeyval-view.sty', version 1.1a, 2012/10/16. %
+% This is file 'skeyval-view.sty', version 1.2, 2013/02/10. %
% %
% This package and accompanying files may be distributed and/or %
% modified under the conditions of the LaTeX Project Public License, %
@@ -23,7 +23,7 @@
% skeyval-pstkey.sty, skeyval-pstkey.tex, skeyval-testclass.cls, %
% and skeyval-testpkg.sty. %
% %
-% Copyright (c) 2010-2012 Ahmed Musa (amusa22@gmail.com). %
+% Copyright (c) 2010-2013 Ahmed Musa (amusa22@gmail.com). %
%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
\begingroup
@@ -69,11 +69,10 @@
\NeedsTeXFormat{LaTeX2e}[2011/06/27]
\ProvidesPackage{skeyval-view}
- [2012/10/16 v1.1a Viewer utility for skeyval package (AM)]
+ [2013/02/10 v1.2 Viewer utility for skeyval package (AM)]
\@ifpackageloaded{skeyval}{}{\RequirePackage{skeyval}}
\directkeys*{%
- .prefix=SKVV,
- .family=skvview,
+ .path=SKVV/skvview,
.holder prefix=skvv@,
.initialize keys after define,
.every unknown option={
@@ -101,8 +100,7 @@
\skvnewnumbers[skvv@]{depth,nra}
\directkeys*{
- .prefix=SKVV,
- .family=skvview,
+ .path=SKVV/skvview,
.holder prefix=skvv@,
.initialize after define=false,
.define keys={
@@ -158,6 +156,7 @@
}%
}
\protected\def\skv@ordkey@a#1[#2]#3{%
+ % Pointers have been stripped in \skv@ordkey.
\skvifstrcmpTF{#2}{^skv^}{%
\skvv@tabulate{#1}{ordinary}{[none]}%
}{%
@@ -167,7 +166,7 @@
\skvcsedef{\skv@header#1.@cbk}{\unexpanded{#3}}%
}
\protected\def\skv@cmdkey#1#2[#3]#4{%
- \skv@strippointers{#2}\skvcurrentkey
+ \skv@strippointersfromkey{#2}%
\skvifdefboolTF{skv@st}{%
\skv@definedefault\skvcurrentkey{#3}%
\skvv@tabulate\skvcurrentkey{command}{#3}%
@@ -184,7 +183,7 @@
}
\protected\def\skv@choicekey@g{%
\skvcommaparse*\skv@currlist\skv@prova{%
- \skvexpbracenext\skv@strippointers\skv@prova\skvcurrentkey
+ \skvexpbracenext\skv@strippointersfromkey\skv@prova
\ifx\skv@default\skv@rej
\skvv@tabulate\skvcurrentkey{choice}{[none]}%
\else\skvafterfi
@@ -200,6 +199,7 @@
}%
}
\protected\def\skv@boolkey@c#1#2#3#4{%
+ % Pointers have been stripped in \skv@boolkey.
\skvcsnewif{\skv@zapornot{\skv@zapsw}{#2}}%
\edef\skvv@boolortog{\if\skv@typetogkey toggle\else bool\fi}%
\skvifdefboolTF{skv@st}{%
@@ -219,7 +219,7 @@
% #2: styles, #3: default, #4: callback
\protected\def\skv@appendstyles@a#1#2[#3]#4{%
\skvcommaparse{#1}\skv@prova{%
- \skvexpbracenext\skv@strippointers\skv@prova\skvcurrentkey
+ \skvexpbracenext\skv@strippointersfromkey\skv@prova
\skvexpanded{%
\skvifstrcmpTF{#3}{^skv^}{%
\skvv@tabulate{\skvcurrentkey}{style}{[none]}%
@@ -246,18 +246,18 @@
\skvv@coliitrue\skvv@coliiitrue\skvv@colivtrue\skvv@colvtrue
\else
\skvsetnumber\skvv@nra\@ne
- \@expandtwoargs\skv@in@{,prefix,}{,\skvv@columns,}%
+ \@expandtwoargs\skvtestifin{,prefix,}{,\skvv@columns,}%
\ifin@\skvadvanceno\skvv@nra\@ne\skvv@coliitrue\else\skvv@coliifalse\fi
- \@expandtwoargs\skv@in@{,family,}{,\skvv@columns,}%
+ \@expandtwoargs\skvtestifin{,family,}{,\skvv@columns,}%
\ifin@\skvadvanceno\skvv@nra\@ne\skvv@coliiitrue\else\skvv@coliiifalse\fi
- \@expandtwoargs\skv@in@{,type,}{,\skvv@columns,}%
+ \@expandtwoargs\skvtestifin{,type,}{,\skvv@columns,}%
\ifin@
\skvadvanceno\skvv@nra\@ne\skvv@colivtrue
\else
- \@expandtwoargs\skv@in@{,key type,}{,\skvv@columns,}%
+ \@expandtwoargs\skvtestifin{,key type,}{,\skvv@columns,}%
\ifin@\skvadvanceno\skvv@nra\@ne\skvv@colivtrue\else\skvv@colivfalse\fi
\fi
- \@expandtwoargs\skv@in@{,default,}{,\skvv@columns,}%
+ \@expandtwoargs\skvtestifin{,default,}{,\skvv@columns,}%
\ifin@\skvadvanceno\skvv@nra\@ne\skvv@colvtrue\else\skvv@colvfalse\fi
\fi
\ifskvv@view
@@ -334,8 +334,7 @@
}
\directkeys*{
- .prefix=SKVV,
- .family=skvvshow,
+ .path=SKVV/skvvshow,
.holder prefix=skvvs@,
.initialize keys after define,
.new keys={
diff --git a/Master/texmf-dist/tex/latex/skeyval/skeyval.sty b/Master/texmf-dist/tex/latex/skeyval/skeyval.sty
index fce36938787..010ce8c51fd 100644
--- a/Master/texmf-dist/tex/latex/skeyval/skeyval.sty
+++ b/Master/texmf-dist/tex/latex/skeyval/skeyval.sty
@@ -1,5 +1,19 @@
%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
-% This is file 'skeyval.sty', version 1.1a, 2012/10/16. %
+% This is file 'skeyval.sty', version 1.2, 2013/02/10. %
+% %
+% NOTE %
+% %
+% Beginning from version 1.0, 2012/09/01, the skeyval package has changed %
+% radically. Users of pre-version 1.0 of the package can load it now by %
+% calling: %
+% %
+% \usepackage[compatibility]{skeyval} %
+% \RequirePackage[compatibility]{skeyval} %
+% or %
+% \usepackage{skeyval-bc} %
+% \RequirePackage{skeyval-bc} %
+% %
+% LICENSE %
% %
% This package and accompanying files may be distributed and/or %
% modified under the conditions of the LaTeX Project Public License, %
@@ -15,6 +29,8 @@
% implied warranties of merchantability and fitness for a particular %
% purpose. %
% %
+% DISTRIBUTION %
+% %
% The following files constitute the skeyval bundle and must be %
% distributed as a whole: %
% %
@@ -23,7 +39,7 @@
% skeyval-pstkey.sty, skeyval-pstkey.tex, skeyval-testclass.cls, %
% and skeyval-testpkg.sty. %
% %
-% Copyright (c) 2010-2012 Ahmed Musa (amusa22@gmail.com). %
+% Copyright (c) 2010-2013 Ahmed Musa (amusa22@gmail.com). %
%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
\begingroup
@@ -67,19 +83,19 @@
\do 032=10,033=12,036=03,038=04,040=12,041=12,042=12,043=12,%
059=12,045=12,047=12,058=12,063=12,091=12,093=12,126=13,\do=,%
-\ProvidesPackage{skeyval}[2012/10/16 v1.1a Robust key-value parser (AM)]
+\ProvidesPackage{skeyval}[2013/02/10 v1.2 Robust key-value parser (AM)]
\NeedsTeXFormat{LaTeX2e}[2011/06/27]
\input skeyval-core
-\skvrobustdef*\skvAfterEndPackage{%
+\skvrobustdef*\skvafterendpackage{%
\skvifcsdefTF{\@currname.\@currext-skv@endpkghook}{}{%
\@namedef{\@currname.\@currext-skv@endpkghook}{}%
}%
\expandafter\g@addto@macro
\csname\@currname.\@currext-skv@endpkghook\endcsname
}
-\skvrobustdef*\skvAfterPackage#1{%
+\skvrobustdef*\skvafterpackage#1{%
\skvafterbegindocument{%
\skvifcsdefTF{ver@#1.\@pkgextension}{}{%
\skv@warn{Package '#1' was never loaded}%
@@ -99,13 +115,12 @@
}%
\unexpanded\expandafter{\@popfilename}%
}
+\skvundef\skv@documentclass
\skvrobustdef*\skv@getdocumentclass{%
- \skv@swafalse
- \ifx\@filelist\@undefined\else
- \ifx\@filelist\relax\else
- \ifx\@filelist\@gobble\else\skv@swatrue\fi
- \fi\fi
- \ifskv@swa
+ \ifcase0%
+ \ifx\@filelist\@undefined 1\fi
+ \ifx\@filelist\relax 1\fi
+ \ifx\@filelist\@gobble 1\fi\relax
\skvcommaparse*\@filelist\skv@tempa{%
\filename@parse\skv@tempa
\ifx\filename@ext\@clsextension
@@ -119,20 +134,22 @@
}%
\fi
}
-\skv@getdocumentclass
+
+% The following packages need access to the original \@classoptionslist:
+\skvnewdef*\skv@optionprocessorpackages{%
+ xkeyval,kvoptions,catoptions,biblatex,pgfopts,ltxkeys%
+}
% Filter class options to remove those with '=':
\skvrobustdef*\skv@filterclassoptions{%
- \skv@swafalse
- \ifx\@classoptionslist\@undefined\else
- \ifx\@classoptionslist\relax\else\skv@swatrue\fi
- \fi
- \ifskv@swa
- \let\skv@filterclassoptions\relax
+ \ifcase0%
+ \ifx\@classoptionslist\@undefined 1\fi
+ \ifx\@classoptionslist\relax 1\fi\relax
+ \global\let\skv@filterclassoptions\relax
\skvkvnormalize\@classoptionslist
- \let\skv@origclassoptlist\@classoptionslist
+ \let\skvoriginalclassoptionslist\@classoptionslist
\let\skv@classoptionslist\@classoptionslist
\let\@classoptionslist\@empty
- \skvcommaloop*\skv@origclassoptlist\skv@tempa{%
+ \skvcommaloop*\skvoriginalclassoptionslist\skv@tempa{%
\skvxifinTF{=}{\skvexpandonce\skv@tempa}{}{%
\skvaddtolist*\@classoptionslist\skv@tempa
}%
@@ -140,11 +157,9 @@
\def\@fileswith@ptions##1[##2]##3{%
\edef\skv@tempa{\unexpanded{##3}}%
\skvcsvnormalize\skv@tempa
- % The following packages need access to the original
- % \@classoptionslist.
- \skvcommaloop{xkeyval,kvoptions,keyval2e,ltxkeys}\skv@prova{%
+ \skvcommaloop*\skv@optionprocessorpackages\skv@prova{%
\skvxifinTF{,\skv@prova,}{,\skv@tempa,}{%
- \let\@classoptionslist\skv@origclassoptlist
+ \let\@classoptionslist\skvoriginalclassoptionslist
\skvbreakloop
}{}%
}%
@@ -153,15 +168,6 @@
}%
\fi
}
-\skvifdefFT\skv@documentclass{%
- \let\skv@documentclass\@empty
- \let\skv@classoptionslist\@empty
- \edef\@popfilename{%
- \skvexpandonce\@popfilename\skv@filterclassoptions
- }%
-}{%
- \skv@filterclassoptions
-}
\skvrobustdef*\skvbeforebegindocument{%
\skvgappendtomacro\skv@beforebegindoc
}
@@ -187,7 +193,7 @@
}
\skvrobustdef*\skv@notprerr#1{%
\@latex@error{Command \detokenize{#1} should be used only
- in preamble}\@ehd
+ in preamble}\skv@ehd
}
\skvnewdef*\skv@everypagehook{}
\skvrobustdef*\skvatbegineverypage{\skvgappendtomacro\skv@everypagehook}
@@ -206,29 +212,37 @@
\skvnewdef*\skv@preamblecmdhook{}
\skvrobustdef*\skvonlypreamble#1{%
- \def\do##1{%
+ \def\skv@provb##1{%
+ \skvifntypeTF{##1}{}{%
+ \skv@err{More than one macro
+ \MessageBreak '\detokenize{##1}'.
+ \MessageBreak Maybe a comma is missing in the list}\skv@ehd
+ }%
\skvxifinTF{\detokenize{\do##1}}{\skvoxdetok\skv@preamblecmdhook}{%
\skv@warn{Command '\noexpand##1' multiply
\MessageBreak submitted to \string\skvonlypreamble: ignored}%
}{%
\xdef\skv@preamblecmdhook{%
- \skvexpandonce\skv@preamblecmdhook
- \unexpanded{\do##1}%
+ \skvexpandonce\skv@preamblecmdhook\unexpanded{\do##1}%
}%
}%
}%
\skvcommaparse{#1}\skv@prova{%
- \expandafter\do\expandafter{\skv@prova}%
+ \expandafter\skv@provb\expandafter{\skv@prova}%
}%
}
\AtEndOfPackage{%
\skvafterbegindocument{%
\def\do#1{%
\skvifdefTF#1{%
- \gdef#1{\@latexerr{'\string#1' is a preamble command}\@ehd}%
+ \gdef#1{\@latexerr{'\string#1' is a preamble command}\skv@ehd}%
}{%
- \@@warning{Undefined command '\unexpanded{#1}'
- appeared in \string\skvonlypreamble}%
+ \ifx\relax#1\else
+ \@@warning{Undefined command '\unexpanded{#1}'
+ \MessageBreak appeared in \string\skvonlypreamble.
+ \MessageBreak Only defined commands should be
+ \MessageBreak submitted to \string\skvonlypreamble.}%
+ \fi
}%
}%
\skv@preamblecmdhook
@@ -242,7 +256,7 @@
% \skvunknownoptionhandler[<prefixes>]<<families>>{<handler>}
%
\skvrobustdef*\skvunknownoptionhandler{%
- \skv@testopt\skv@unknownoptionhandler\skv@defaultpref
+ \skv@testopt\skv@unknownoptionhandler\skvdefaultprefix
}
\skvrobustdef*\skv@unknownoptionhandler[#1]{%
\skvifnextchar<{\skv@unkn@wnoptionhandler{#1}}%
@@ -251,14 +265,12 @@
\skvrobustdef*\skv@unkn@wnoptionhandler#1<#2>{%
\skv@unknownkeyhandler[#1]{#2}%
}
-
-
\skvrobustdef*\skv@testopte#1{\skv@testopta{\skv@t@stopte{#1}}}
-\skvrobustdef*\skv@t@stopte#1{\skv@testopt{\skv@t@st@pte{#1}}\skv@defaultpref}
+\skvrobustdef*\skv@t@stopte#1{\skv@testopt{\skv@t@st@pte{#1}}\skvdefaultprefix}
\skvrobustdef*\skv@t@st@pte#1[#2]{%
% Only one prefix is allowed:
\skvxifinTF{,}{\detokenize{#2}}{%
- \skv@err{Only one prefix is allowed, but you gave '#2'}\@ehd
+ \skv@err{Only one prefix is allowed, but you gave '#2'}\skv@ehd
}{%
\skv@makeprefix{#2}%
\skvifnextchar<{\skv@@t@st@pte{#1}}%
@@ -289,6 +301,14 @@
\let\skvdefkey\skvvoidkey
\skv@dox@a
}
+% \skvdeclareobsoleteoption
+% [<pref>]{<fam>}{<obsolete key>}{<new key>}[<defa>]{<callback>}
+\skvrobustdef*\skvdeclareobsoleteoption{%
+ \let\@fileswith@pti@ns\@badrequireerror
+ \let\skvdefkey\skvobsoletekey
+ \skv@dox@a
+}
+
% \skvdeclarebooloption[<pref>]<<fam>>[<mp>]{<key>}[<defa>]{<callback>}
\skvrobustdef*\skvdeclarebooloption{%
\let\@fileswith@pti@ns\@badrequireerror
@@ -302,44 +322,40 @@
\skv@dox@a
}
-% Our default action for unknown options is tied to \@currname & \@currext:
+% Our default action for unknown options is tied to \@currname
+% and \@currext:
\skvrobustdef\skv@dox#1{%
- \skvcsedef{skv@dox@\@currname @\@currext}{%
+ \skvcsedef{skv@dox@\@currname.\@currext}{%
\unexpanded{%
- \begingroup
\ifx\skvcurrentvalue\skv@novaluetoks
\def\skvcurrentvalue{no value}%
\fi
- \@onelevel@sanitize\CurrentOption
- \@onelevel@sanitize\skvcurrentvalue
#1%
- \endgroup
}%
}%
}
-\skvrobustdef*\skv@dox@a{\skv@testopt\skv@dox@b\skv@defaultpref}
+\skvrobustdef*\skv@dox@a{\skv@testopt\skv@dox@b\skvdefaultprefix}
\skvrobustdef*\skv@dox@b[#1]{%
- \skvifnextchar<%
- {\skv@dox@c{#1}}{\skv@dox@c{#1}<\@currname.\@currext>}%
+ \skvifnextchar<{\skv@dox@c{#1}}{\skv@dox@c{#1}<\@currname.\@currext>}%
}
\skvrobustdef*\skv@dox@c#1<#2>{\skvdefkey[#1]{#2}}
% Declare options with default values that will be used when the options
% are called without user values.
%
-% \skvDeclarePassedOptions[<pref>]{<fam>}{<option>=<default>,...}
+% \skvdeclarepassedoptions[<pref>]{<fam>}{<option>=<default>,...}
%
% Example:
%
-% \skvDeclarePassedOptions[KV]{fam}{%
+% \skvdeclarepassedoptions[KV]{fam}{%
% hyperref={colorlinks,breaklinks},xcolor=svgnames
% }
%
-\skvrobustdef*\skvDeclarePassedOptions{%
- \skv@testopt\skv@declarepassedoptions\skv@defaultpref
+\skvrobustdef*\skvdeclarepassedoptions{%
+ \skv@testopt\skv@declarepassedoptions\skvdefaultprefix
}
\skvrobustdef*\skv@declarepassedoptions[#1]#2#3{%
- \skvparsekeyvals{#3}\skv@tempa{%
+ \skvparsekvlist{#3}\skv@tempa{%
\skvexpbracenext\skv@kvsplit\skv@tempa{%
\skvdeclareoption[#1]<#2>{##1}[##2]{%
\skvifcsdefTF{ver@##1.sty}{%
@@ -347,9 +363,9 @@
\MessageBreak now you're passing options to it.
\MessageBreak Instruction ignored}%
}{%
- \skvPassOptionsToPackage{####1}{##1}%
+ \skvpassoptionstopackage{####1}{##1}%
\AtBeginDocument{%
- \skvifpackageloaded{##1}{}{%
+ \skvifpackageloadedTF{##1}{}{%
\skv@warn{Options were passed to package
\MessageBreak '##1' but it was never loaded}%
}%
@@ -359,9 +375,9 @@
}%
}%
}
-% \skvPassOptionsToPackage{<opts>}{<pkg>}
-\skvrobustdef*\skvPassOptionsToPackage{\skv@passoptions{sty}}
-\skvrobustdef*\skvPassOptionsToClass{\skv@passoptions{cls}}
+% \skvpassoptionstopackage{<opts>}{<pkg>}
+\skvrobustdef*\skvpassoptionstopackage{\skv@passoptions{sty}}
+\skvrobustdef*\skvpassoptionstoclass{\skv@passoptions{cls}}
\skvrobustdef*\skv@passoptions#1#2#3{%
\begingroup
\edef\@elt{opt@\skvtrimspace{#3}.#1}%
@@ -372,14 +388,16 @@
\endgroup
}
-% \skvDeclarePassedOptionsLoadPackage
+% Pass options to package and load the package after processing options.
+%
+% \skvdeclarepassedoptionsloadpackage
% [<pref>]{<fam>}{<option>=<default>,...}
%
-\skvrobustdef*\skvDeclarePassedOptionsLoadPackage{%
- \skv@testopt\skv@declarepassedoptions@load\skv@defaultpref
+\skvrobustdef*\skvdeclarepassedoptionsloadpackage{%
+ \skv@testopt\skv@declarepassedoptions@load\skvdefaultprefix
}
\skvrobustdef*\skv@declarepassedoptions@load[#1]#2#3{%
- \skvparsekeyvals{#3}\skv@tempa{%
+ \skvparsekvlist{#3}\skv@tempa{%
\skvexpbracenext\skv@kvsplit\skv@tempa{%
\skvdeclareoption[#1]<#2>{##1}[##2]{%
\skvifcsdefTF{ver@##1.sty}{%
@@ -418,86 +436,134 @@
% 4. The \ProcessOptionsX of xkeyval package doesn't expect any plus (+)
% suffix: it processes options only in a single family.
%
-\skvrobustdef*\skvprocessoptions{\skv@testopte\skv@pox}
+% 5. \skvpackagelist contains the list of loaded packages with their
+% options that are found on the current paths. See
+% <https://groups.google.com/forum/#!topic/comp.text.tex/XErNCMcT_jc>
+% for the rationale. Example:
+%
+% \usepackage[option1,option2]{foobar}
+% \show\skvpackagelist
+% \expandafter\show\csname foobar.sty.poxkeys\endcsname
+%
+\skvnewlet\skvpackagelist\@empty
+\skvrobustdef*\skvprocessoptions{%
+ \skv@getdocumentclass
+ \ifdefined\skv@documentclass
+ \global\let\skv@getdocumentclass\relax
+ \skv@filterclassoptions
+ \fi
+ \skv@testopte\skv@pox
+}
+\skvnewlet\skv@savprocessoptions\skvprocessoptions
+\skvrobustdef*\skv@badprocessoptions{%
+ \skv@testopte{%
+ \skv@err{\noexpand\skvprocessoptions can't be nested}\skv@ehd
+ }%
+}
\skvrobustdef*\skv@pox[#1]{%
\skv@inpoxtrue
\let\@fileswith@pti@ns\@badrequireerror
- \edef\skv@userclassorpackage{\@currname.\@currext}%
+ \let\skvprocessoptions\skv@badprocessoptions
\begingroup
- \let\skv@clsoptsfound\@empty
- \let\skv@clsorpkgopts\@empty
+ \edef\skv@userclassorpackage{\@currname.\@currext}%
+ \let\skv@classoptionsfound\@empty
+ \let\skv@classorpackageoptions\@empty
+ % The list of pox keys for each family, simply for taking
+ % pox keys outside the current scope:
\let\skv@exitpoxkeys\@empty
- \skvifxTF\skv@userclassorpackage\skv@documentclass{%
+ % The list of pox keys in all familes:
+ \let\skvcurrentpoxkeys\@empty
+ \ifx\skv@userclassorpackage\skv@documentclass
+ \skv@inclasstrue
\let\@unusedoptionlist\skv@classoptionslist
- }{%
- \ifcase0\ifx\skv@classoptionslist\@empty\else
- \ifx\skv@classoptionslist\relax\else\ifskv@st1\fi\fi\fi\relax
- \skv@swafalse
- \else
- \skv@swatrue
- \fi
- \skvifboolFT{skv@swa}{}{%
- \def\ifkeyundef##1##2##3{\skvexpanded{\skvifkeydefFT[##1]{##2}{##3}}}%
- \skvcommaloop*\skv@classoptionslist\CurrentOption{%
- \expandafter\expandafter\expandafter
- \skv@g@tkeyname\CurrentOption=\skv@nil\skvcurrentkey
- % Test if key is defined in one of the families. The search will
- % stop as soon as the key is found in any of the families.
- \ifkeyundef\skvcurrentprefix\skv@fams\skvcurrentkey{}{%
- \edef\skv@clsoptsfound{%
- \skvexpandonce\skv@clsoptsfound
- \ifx\skv@clsoptsfound\@empty\else,\fi
- \skvexpandonce\CurrentOption
+ \else
+ \skv@inclassfalse
+ \ifcase0%
+ \ifx\skv@classoptionslist\@undefined 1\fi
+ \ifx\skv@classoptionslist\@empty 1\fi
+ \ifx\skv@classoptionslist\relax 1\fi\relax
+ \ifskv@st
+ \def\ifkeyundef##1##2##3{\skvexpanded{\skvifkeydefFT[##1]{##2}{##3}}}%
+ \skvcommaloop*\skv@classoptionslist\CurrentOption{%
+ \expandafter\expandafter\expandafter
+ \skv@g@tkeyname\CurrentOption=\skv@getname@nil\skvcurrentkey
+ % Test if key is defined in one of the families. The search will
+ % stop as soon as the key is found in any of the families.
+ \ifkeyundef\skvcurrentprefix\skv@fams\skvcurrentkey{}{%
+ \edef\skv@classoptionsfound{%
+ \skvaddlist,\skv@classoptionsfound\skvexpandonce\CurrentOption
+ }%
+ \expandafter\skv@removeoption\expandafter{\CurrentOption}%
}%
- \expandafter\skv@useoption\expandafter{\CurrentOption}%
}%
- }%
- \ifx\skv@clsoptsfound\@empty\else\skvafterfi
- \skvexpbracenext\skv@getkeynames\skv@clsoptsfound\skv@tempd
- \skvexpbracenext\skv@getpoxkeys\skv@tempd
+ \ifx\skv@classoptionsfound\@empty\else
+ \skvexpbracenext\skv@getnamesofkeys\skv@classoptionsfound\skv@tempd
+ \skvexpbracenext\skv@getpoxkeys\skv@tempd
+ \fi
\fi
- }%
- }%
- \skvletcs\skv@clsorpkgopts{opt@\@currname.\@currext}%
- \skvifxTF\skv@clsorpkgopts\@empty{}{%
- \skvifxTF\skv@clsorpkgopts\relax{}{%
- \skvexpbracenext\skv@getkeynames\skv@clsorpkgopts\skv@tempd
- \skvexpbracenext\skv@getpoxkeys\skv@tempd
- }%
- }%
- % Package options have higher priority than class options. Hence
- % filter class options \skv@clsoptsfound that are also present
- % as package options \skv@clsorpkgopts:
- \ifcase0\ifx\skv@clsoptsfound\@empty\else
- \ifx\skv@clsorpkgopts\@empty\else
- \ifx\skv@clsorpkgopts\relax\else1\fi\fi\fi\relax
- \else\skvafterfi
+ \fi
+ \fi
+ \skvletcs\skv@classorpackageoptions{opt@\@currname.\@currext}%
+ \ifx\skv@classorpackageoptions\relax
+ \def\skv@classorpackageoptions{}%
+ \fi
+ \skvifemptyTF\skv@classorpackageoptions{}{%
+ \skvexpbracenext\skv@getnamesofkeys\skv@classorpackageoptions\skv@tempd
+ \skvexpbracenext\skv@getpoxkeys\skv@tempd
+ % Package options have higher priority than class options. Hence
+ % filter class options \skv@classoptionsfound that are also present
+ % as package options \skv@classorpackageoptions:
\skvifxTF\skv@userclassorpackage\skv@documentclass{}{%
- \skvcommaloop*\skv@clsoptsfound\CurrentOption{%
- \expandafter\expandafter\expandafter
- \skv@g@tkeyname\CurrentOption=\skv@nil\skv@tempa
- \skvxifinTF{,\skvoxdetok\skv@tempa,}{,\skvoxdetok\skv@tempd,}{}{%
- \edef\skv@clsorpkgopts{%
- \skvexpandonce\skv@clsorpkgopts,\skvexpandonce\CurrentOption
+ \skvifemptyTF\skv@classoptionsfound{}{%
+ \skvcommaloop*\skv@classoptionsfound\CurrentOption{%
+ \expandafter\skv@g@tkeyname\CurrentOption=\skv@getname@nil\skv@tempa
+ \skvxifinTF{,\skvoxdetok\skv@tempa,}{,\skvoxdetok\skv@tempd,}{}{%
+ \edef\skv@classorpackageoptions{%
+ \skvaddlist,\skv@classorpackageoptions
+ \skvexpandonce\CurrentOption
+ }%
}%
}%
}%
}%
+ }%
+ % Get document class options that are on the current paths:
+ \ifx\skv@userclassorpackage\skv@documentclass
+ \def\skvclassoptionsfound{}%
+ \skvcommaloop*\skv@classorpackageoptions\skv@prova{%
+ \expandafter\skv@g@tkeyname\skv@prova=\skv@getname@nil\skvcurrentkey
+ \edef\skv@prova{[\skvcurrentprefix]{\skv@fams}{\skvcurrentkey}}%
+ \expandafter\skvifkeydefTF\skv@prova{%
+ \edef\skvclassoptionsfound{%
+ \skvaddlist,\skvclassoptionsfound\skvcurrentkey
+ }%
+ }{}%
+ }%
+ \else
+ \let\skvclassoptionsfound\skv@classoptionsfound
\fi
+ % \skvpackagelist is populated by all calls to \skvprocessoptions.
+ \skvletcs\skv@prova{\@currname.\@currext.poxkeys}%
+ \edef\skvpackagelist{%
+ \skvaddlist,\skvpackagelist
+ \skvifdefFT\skv@prova{}{\@currname.\@currext{\skv@prova}}%
+ }%
+ \let\do\skvcmdexit
\skvexpanded{\endgroup
- \skv@exitpoxkeys
- \skvcmdexit\@unusedoptionlist
- % There may be preset keys even when \skv@clsorpkgopts is empty:
+ \do\skvclassoptionsfound\do\skvcurrentpoxkeys
+ \do\skvpackagelist\do\@unusedoptionlist
+ \skvboolexit\ifskv@inclass\skv@exitpoxkeys
+ % There may be preset keys even when \skv@classorpackageoptions is empty:
\skvsetkeys\ifskv@pl+\fi[\skvcurrentprefix]{\skv@fams}[#1]%
- {\skvexpandonce\skv@clsorpkgopts}%
+ {\skvexpandonce\skv@classorpackageoptions}%
}%
- \skvcslet{skv@dox@\@currname @\@currext}\relax
- \skvinitializermkeys*\skvcurrentprefix\skv@fams
+ \skvcslet{skv@dox@\@currname.\@currext}\relax
\skv@inpoxfalse
\let\@fileswith@pti@ns\@@fileswith@pti@ns
+ \let\skvprocessoptions\skv@savprocessoptions
\AtEndOfPackage{\let\@unprocessedoptions\relax}%
- \csname skv@\@currname @\@currext @afterprocess@hook\endcsname
- \skvcslet{skv@\@currname @\@currext @afterprocess@hook}\relax
+ \csname skv@\@currname.\@currext @afterprocess@hook\endcsname
+ \skvcslet{skv@\@currname.\@currext @afterprocess@hook}\relax
}
% \skvprocessoptionswithclassoptions*+[<pref>]{<fams>}[<na>]
@@ -506,9 +572,11 @@
% user hasn't put it.
%
\skvrobustdef*\skvprocessoptionswithclassoptions{%
- \skv@testopte\skv@pox@copyclassoptions
+ \skv@testopte\skv@processoptionswithclassoptions
+}
+\skvrobustdef*\skv@processoptionswithclassoptions[#1]{%
+ \skv@sttrue\skv@pox[#1]%
}
-\skvrobustdef*\skv@pox@copyclassoptions[#1]{\skv@sttrue\skv@pox[#1]}
% \skvprocessoptionswithoutclassoptions*+[<pref>]{<fams>}[<na>]
%
@@ -516,175 +584,189 @@
% user has put it.
%
\skvrobustdef*\skvprocessoptionswithoutclassoptions{%
- \skv@testopte\skv@pox@nocopyclassoptions
+ \skv@testopte\skv@processoptionswithoutclassoptions
+}
+\skvrobustdef*\skv@processoptionswithoutclassoptions[#1]{%
+ \skv@stfalse\skv@pox[#1]%
}
-\skvrobustdef*\skv@pox@nocopyclassoptions[#1]{\skv@stfalse\skv@pox[#1]}
% \skv@getpoxkeys{<keys>}
%
-% Get pox keys (ie, keys processed as options) from package or
-% class options.
+% 1. Get pox keys (ie, keys processed as options) from package or
+% class options.
+% 2. This isn't a user command! See \skvgetdefinedkeys in file
+% skeyval-core.tex.
\skvrobustdef*\skv@getpoxkeys#1{%
\begingroup
- \def\xiftest{%
- \skvexpanded{%
- \noexpand\skvifkeyinfamiliesFT
- [\skvcurrentprefix]{\skv@fams}{\skvcurrentkey}%
+ \skvcommaloop*\skv@fams\skvcurrentfamily{%
+ \skv@makeheader\skvcurrentfamily
+ % Prepare to take poxkeys outside the group:
+ \skvxifinTF{\skvoxdetok\skv@header}{\skvoxdetok\skv@exitpoxkeys}{}{%
+ \edef\skv@exitpoxkeys{%
+ \skvexpandonce\skv@exitpoxkeys
+ \noexpand\skvcsexit{\skvcurrentpath.@poxkeys}%
+ }%
}%
- }%
- \skvcommaloop{#1}\skvcurrentkey{%
- \xiftest{}{%
- % \skv@header is formed in the search for the key:
- \skvletcs\skv@prova{\skv@header.@poxkeys}%
- \skvifdefTF\skv@prova{%
- \skvxifinTF{,\skvoxdetok\skvcurrentkey,}{,\skvoxdetok\skv@prova,}{}{%
- \skvcsedef{\skv@header.@poxkeys}{\skv@prova,\skvcurrentkey}%
- }%
- }{%
- \skvcsedef{\skv@header.@poxkeys}{\skvcurrentkey}%
+ \edef\skv@prova{\@currname.\@currext.poxkeys}%
+ \skvxifinTF{\skvoxdetok\skv@prova}{\skvoxdetok\skv@exitpoxkeys}{}{%
+ \edef\skv@exitpoxkeys{%
+ \skvexpandonce\skv@exitpoxkeys\noexpand\skvcsexit{\skv@prova}%
}%
- \skvxifinTF{\skvoxdetok\skv@header}{\skvoxdetok\skv@exitpoxkeys}{}{%
- \edef\skv@exitpoxkeys{%
- \skvexpandonce\skv@exitpoxkeys
- \noexpand\skvcsexit{\skv@header.@poxkeys}%
+ }%
+ \skvcommaloop{#1}\skvcurrentkey{%
+ \skvifcsdefFT{\skv@header\skvcurrentkey.@cbk}{}{%
+ \skvletcs\skv@prova{\skvcurrentpath.@poxkeys}%
+ \skvifdefTF\skv@prova{%
+ \skvxifinTF{,\skvcurrentkey,}{,\skv@prova,}{}{%
+ \skvcsedef{\skvcurrentpath.@poxkeys}{%
+ \skvaddlist,\skv@prova\skvcurrentkey
+ }%
+ }%
+ }{%
+ \skvcsedef{\skvcurrentpath.@poxkeys}{\skvcurrentkey}%
+ }%
+ \skvletcs\skv@prova{\@currname.\@currext.poxkeys}%
+ \skvifdefTF\skv@prova{%
+ \skvxifinTF{,\skvcurrentkey,}{,\skv@prova,}{}{%
+ \skvcsedef{\@currname.\@currext.poxkeys}{%
+ \skvaddlist,\skv@prova\skvcurrentkey
+ }%
+ }%
+ }{%
+ \skvcsedef{\@currname.\@currext.poxkeys}{\skvcurrentkey}%
+ }%
+ \skvxifinTF{,\skvcurrentkey,}{,\skvcurrentpoxkeys,}{}{%
+ \edef\skvcurrentpoxkeys{%
+ \skvaddlist,\skvcurrentpoxkeys\skvcurrentkey
+ }%
}%
}%
}%
}%
+ \let\do\skvcmdexit
\skvexpanded{\endgroup
- \skvcmdexit\skv@exitpoxkeys
+ \do\skvcurrentpoxkeys
+ % We need the list in \skv@exitpoxkeys outside the current scope.
+ % It will be used to take poxkeys (on each path) outside the scope
+ % in \skv@pox:
+ \do\skv@exitpoxkeys
+ % We need the poxkeys on each path outside the current scope:
\skv@exitpoxkeys
}%
}
% +++++++++ Utilities for handling options via \directkeys +++++++++%
-\skvrobustdef*\dirkeys@declareoptions@a{%
- \let\@fileswith@pti@ns\@badrequireerror
- \skv@dox
-}
-\skvrobustdef*\dirkeys@declareoptions@b#1{%
+% \dirkeys@declareoptions{<star>}{<list>}
+%
+% <star>, if present, means new options.
+%
+\skvrobustdef*\dirkeys@declareoptions#1#2{%
\let\@fileswith@pti@ns\@badrequireerror
- \skv@inopttrue
\begingroup
- \edef\skv@tempb{\unexpanded{#1}}%
+ % The boolean skv@inopt differs from skv@inpox. skv@inopt is only
+ % meant to set the default family in \dirkeys@setdefaultpath
+ % when dealing with options.
+ \skv@inopttrue
\def\skv@tempa{}%
- \def\do##1##2{%
+ \edef\skv@tempb{\unexpanded{#2}}%
+ \def\skv@pathdo##1##2{%
\edef\skv@tempa{%
\skvexpandonce\skv@tempa
- \skvdefinekeys\ifskv@handlerswa*\fi[##1]{##2}%
+ \skvdefinekeys#1[##1]{##2}%
[\dirkeys@holderprefixtoks]{\skvexpandonce\skv@tempb}%
}%
}%
- \dirkeys@getcurrentroots\do
+ \dirkeys@pathlist
\expandafter\endgroup\skv@tempa
- \skv@inoptfalse
}
-% % \dirkeys@executeoptions{<options>}
+% \dirkeys@executeoptions{<plus sign or empty>}{<kvlist>}
%
-% 1. Ececute options on all the prevailing paths. If any of
-% the options isn't found on a path, report error (ie,
-% don't save the key to the list of 'remaining keys'). Unknown
-% options should be flagged by an error immediately.
-% 2. There is no plus (+) variant for this command/handler.
-% 3. It is the user's responsibility to ensure that keys exist on
-% current paths. This is easier to enforce if there is only one
-% current path (prefix and family).
+% 1. <no-plus> = Execute options on ONLY the first path found. If an
+% option isn't found on the given paths, report error (ie,
+% don't save the option to the list of 'remaining keys'). Unknown
+% options should be flagged by an error immediately. Hence no
+% star (*) form of \dirkeys@executeoptions.
+% 2. <plus> = Execute options on all the prevailing paths. If an
+% option isn't found on the given paths, flag error.
%
-\skvrobustdef*\dirkeys@executeoptions#1{%
- \skv@inopttrue
+\skvrobustdef*\dirkeys@executeoptions#1#2{%
\begingroup
- % Don't confuse parameter characters in #1 with those of \do:
- \edef\skv@tempb{\unexpanded{#1}}%
- \def\skv@tempa{}%
- \def\do##1##2{%
- \skvletcs\skv@igkeys{##1/##2/.@ignoredkeys}%
- \skvifdefTF\skv@igkeys{}{\def\skv@igkeys{}}%
- \edef\skv@tempa{%
- \skvexpandonce\skv@tempa
- \skvsetkeys[##1]{##2}[\skv@igkeys]{\skvexpandonce\skv@tempb}%
- }%
- }%
- \dirkeys@getcurrentroots\do
- \expandafter\endgroup\skv@tempa
- \skv@inoptfalse
-}
-
-% \dirkeys@executeoptions@b{<options>}
-%
-% 1. Ececute options in all the prevailing families. If any of
-% the options isn't found in at least one family, report error (ie,
-% don't save the key to the list of 'remaining keys'). Unknown options
-% should be flagged immediately.
-% 2. The plus (+) variant will execute the option in each family in
-% which the option is found.
-% 3. The difference between \dirkeys@executeoptions and
-% \dirkeys@executeoptions@b is that in \dirkeys@executeoptions
-% the prefixes can be more than one. Options will be executed for
-% all combinations of prefixes and families.
-% 4. Prevailing prefixes can't be more than one.
-%
-\skvrobustdef*\dirkeys@executeoptions@b#1{%
\skv@inopttrue
- \begingroup
- \dirkeys@collectpaths
- \skvexpanded{\endgroup
- \skvsetkeys+[\skv@tempa]{\skv@tempb}[\skv@tempc]%
- }{#1}%
- \skv@inoptfalse
-}
-\skvrobustdef*\dirkeys@collectpaths{%
- \skvemptify{\do\skv@tempa\do\skv@tempb\do\skv@tempc}%
- \def\do##1##2{%
- \skvletcs\skv@igkeys{##1/##2/.@ignoredkeys}%
- \skvifdefTF\skv@igkeys{}{\def\skv@igkeys{}}%
- \skvxifinTF{,##1,}{,\skv@tempa,}{}{%
- \edef\skv@tempa{\skv@tempa\ifx\skv@tempa\@empty\else,\fi##1}%
- }%
- \skvxifinTF{,##2,}{,\skv@tempb,}{}{%
- \edef\skv@tempb{\skv@tempb\ifx\skv@tempb\@empty\else,\fi##2}%
- }%
- \edef\skv@tempc{%
- \skv@tempc\ifx\skv@tempc\@empty\else,\fi\skv@igkeys
+ % If the number of families is greater than one, gnored keys
+ % from different families will mixed. This is the case even in
+ % \skvsetkeys.
+ \skvemptify{\skv@igkeys,\skv@fams}%
+ \@tempcnta\skvz@
+ \def\skv@pathdo##1##2{%
+ \advance\@tempcnta\@ne
+ \def\skv@pref{##1}%
+ \ifnum\@tempcnta=\@ne
+ \def\skv@firstpref{##1}%
+ \else
+ \ifx\skv@pref\skv@firstpref\else
+ \skv@err{You can't use multiple prefixes when
+ \MessageBreak calling the handler '.execute options'.
+ \MessageBreak Check your values of '.prefix' and '.paths'}\skv@ehd
+ \fi
+ \fi
+ \skvxifinTF{,##2,}{,\skv@fams,}{}{%
+ \edef\skv@fams{\skvaddlist,\skv@fams##2}%
}%
+ \skvletcs\skv@prova{##1/##2/.@ignoredkeys}%
+ \ifdefined\skv@prova
+ \edef\skv@igkeys{\skvaddlist,\skv@igkeys\skv@prova}%
+ \fi
}%
- \dirkeys@getcurrentroots\do
- \skvifelementcount*\skv@tempa\tw@
- {\skv@err{You can't submit more than one prefix here}\@ehd}{}
+ \dirkeys@pathlist
+ \ifx\skv@fams\@empty
+ \skv@err{No family before calling '.execute options'}\skv@ehd
+ \fi
+ \skvexpanded{\endgroup
+ \skvsetkeys#1[\skv@pref]{\skv@fams}[\skv@igkeys]%
+ }{#2}%
}
-\skvrobustdef*\dirkeys@processoptions{%
- \skv@inopttrue
+\skvrobustdef*\dirkeys@processoptions#1#2{%
\begingroup
- \def\skv@tempa{}%
- \def\do##1##2{%
- \skvletcs\skv@igkeys{##1/##2/.@ignoredkeys}%
- \skvifdefTF\skv@igkeys{}{\def\skv@igkeys{}}%
- \edef\skv@tempa{%
- \skvexpandonce\skv@tempa
- \skvprocessoptions\ifskv@handlerswa*\fi
- [##1]<##2>[\skv@igkeys]%
+ \skv@inopttrue
+ % If the number of families is greater than one, gnored keys
+ % from different families will mixed. This is the case even in
+ % \skvprocessoptions.
+ \skvemptify{\skv@igkeys,\skv@fams}%
+ \@tempcnta\skvz@
+ \def\skv@pathdo##1##2{%
+ \advance\@tempcnta\@ne
+ \def\skv@pref{##1}%
+ \ifnum\@tempcnta=\@ne
+ \def\skv@firstpref{##1}%
+ \else
+ \ifx\skv@pref\skv@firstpref\else
+ \skv@err{You can't use multiple prefixes when
+ \MessageBreak calling the handler '.process options'.
+ \MessageBreak Check your values of '.prefix' and '.paths'}\skv@ehd
+ \fi
+ \fi
+ \skvxifinTF{,##2,}{,\skv@fams,}{}{%
+ \edef\skv@fams{\skvaddlist,\skv@fams##2}%
}%
+ \skvletcs\skv@prova{##1/##2/.@ignoredkeys}%
+ \ifdefined\skv@prova
+ \edef\skv@igkeys{\skvaddlist,\skv@igkeys\skv@prova}%
+ \fi
}%
- \dirkeys@getcurrentroots\do
- \expandafter\endgroup\skv@tempa
- \skv@inoptfalse
-}
-\skvrobustdef*\dirkeys@processoptions@b{%
- \skv@inopttrue
- \begingroup
- \dirkeys@collectpaths
+ \dirkeys@pathlist
+ \ifx\skv@fams\@empty
+ \skv@err{No family before calling '.process options'}\skv@ehd
+ \fi
\skvexpanded{\endgroup
- \skvprocessoptions\ifskv@handlerswa*\fi
- +[\skv@tempa]<\skv@tempb>[\skv@tempc]%
+ \skvprocessoptions#1#2[\skv@pref]<\skv@fams>[\skv@igkeys]%
}%
- \skv@inoptfalse
}
% ++++++++ Keys for the handler <.mega process options> +++++++++ %
\directkeys*{%
- .prefix=SKV,
- .family=megapox,
+ .path={SKV/megapox},
.holder prefix=dirkeys@pox@,
.initialize keys after define=true,
.new keys={
@@ -692,124 +774,121 @@
\def\dirkeys@pox@igkeys{#1}
\skvstripouterbraces{2}\dirkeys@pox@igkeys
,
- .ord/.options prefix/\skv@defaultpref/
- \skvxifinTF{,}{\detokenize{#1}}{
- \skv@err{Only one prefix is allowed in processing options}\@ehd
- }{
- \def\dirkeys@pox@pref{#1}
+ .ord/{.prefix,.options prefix}/\skvdefaultprefix/
+ \skv@ifoneprefix{#1}{%
+ \edef\dirkeys@pox@pref{#1}
\skvstripouterbraces{2}\dirkeys@pox@pref
+ }{%
+ \skv@err{Only one prefix is allowed in
+ \MessageBreak processing options}\skv@ehd
}
,
- .ord/.options families/\@currname.\@currext/
+ .ord/{.family,.families,.options families,.options family}/
+ \@currname.\@currext/
\edef\dirkeys@pox@fams{#1}
\skvstripouterbraces{2}\dirkeys@pox@fams
+ \skv@makepaths\dirkeys@pox@pref\dirkeys@pox@fams
+ \dirkeys@megapox@pathlist\skv@pathdo
,
- .ord/.copy class options/true/
- \edef\dirkeys@pox@copyclass{\skvifstrcmpTF{#1}{true}{00}{01}}
+ .ord/{path,.paths,.option path,.option paths}/
+ {KV/\@currname.\@currext}/
+ \skv@formatpaths{#1}\dirkeys@megapox@pathlist
+ ,
+ .ord/{.copy class options,.include class options}/true/
+ \edef\dirkeys@pox@copyclass{0\skvifstrcmpTF{#1}{true}{0}{1}}
,
- },
- .styles={
- .prefix/.options prefix=#1,
- .options family/.options families=#1,
- .family/.options families=#1,
- .families/.options families=#1,
- .include class options/.copy class options=#1,
},
}
%\skvshowcs{SKV/megapox/.options family.@cbk}
%\skvshowcs{SKV/megapox/.pref.@cbk}
+\skvnewnumbers[skv@]{megapoxdepth}
\skvrobustdef*\dirkeys@megaprocessoptions#1{%
- \skvpushfunctions\dirkeys@megaprocessoptions{%
- \do\dirkeys@pox@pref\do\dirkeys@pox@fams
+ \skvpushfunctions\dirkeys@megapox{%
+ \do\dirkeys@pathlist\do\skv@pathdo\do\dirkeys@megapox@pathlist
\do\dirkeys@pox@igkeys\do\dirkeys@pox@copyclass
- }\skv@gendepth
- \skv@inopttrue
+ }\skv@megapoxdepth
+ \skvemptify{\dirkeys@megapox@pathlist,\dirkeys@pox@igkeys}%
+ \let\dirkeys@pox@pref\skvdefaultprefix
+ \def\dirkeys@pox@copyclass{01}%
\skvsetkeys[SKV]{megapox}{#1}%
+ \ifx\dirkeys@pox@igkeys\@empty
+ % So that all '...@ignoredkeys' will be undefined:
+ \let\dirkeys@pox@igkeys\undefined
+ \fi
+ \let\dirkeys@pathlist\dirkeys@megapox@pathlist
+ \def\skv@pathdo##1##2{%
+ \skvcslet{##1/##2/.@ignoredkeys}\dirkeys@pox@igkeys
+ }%
+ \dirkeys@pathlist
\skvexpanded{%
- \skvprocessoptions\if\dirkeys@pox@copyclass*\fi+%
- [\dirkeys@pox@pref]<\dirkeys@pox@fams>[\dirkeys@pox@igkeys]%
+ \dirkeys@processoptions\if\dirkeys@pox@copyclass*\fi{+}%
}%
- \skv@inoptfalse
- \skvpopfunctions\dirkeys@megaprocessoptions\skv@gendepth
+ \skvpopfunctions\dirkeys@megapox\skv@megapoxdepth
}
-% +++++++++++++ Handlers for processing options ++++++++++++++ %
+% +++++++++++++ Handlers for executing and processing options ++++++++++++ %
\directkeys*{%
.new handlers={
- .action for unknown options=\dirkeys@declareoptions@a{#1},
- .declare options={
- \skv@handlerswafalse\dirkeys@declareoptions@b{#1}
+ {.action for unknown options,.action for unknown options}={
+ \let\@fileswith@pti@ns\@badrequireerror
+ \skv@dox{#1}
},
- .new options={
- \skv@handlerswatrue\dirkeys@declareoptions@b{#1}
+ {.declare option,.declare options,.define option,.define options}={
+ \dirkeys@declareoptions{}{#1}
},
- .execute options={
- \dirkeys@executeoptions{#1}
+ {.new option,.new options}={
+ \dirkeys@declareoptions{*}{#1}
},
- .execute options+={
- \dirkeys@executeoptions@b{#1}
+ {.execute options,.executeoptions,.execute options in one family}={
+ \dirkeys@executeoptions{}{#1}
},
- .execute options*={
+ {.execute options*,.executeoptions*}={
\skv@err
- {Handler <.execute options*> is undefined}
- {Handler <.execute options> has no star (*) variant,
+ {Handler '.execute options*' is undefined}
+ {Handler '.execute options' has no star (*) variant,
\MessageBreak since we don't want to ignore unknown
\MessageBreak options from within package or class file.}%
},
- .execute options*+={
- \skv@err
- {Handler <.execute options*+> is undefined}
- {Handler <.execute options+> has no star (*) variant,
- \MessageBreak since we don't want to ignore unknown
- \MessageBreak options from within package or class file.}%
+ {.execute options+,.executeoptions+,.execute options in all families}={
+ \dirkeys@executeoptions{+}{#1}
},
% 1. All <.process options> handlers will filter out ignored keys.
% 2. <.process options*> will copy class options.
- % 3. <.process options+> will set options in all the active families
- % in which the options exist.
- % 4. <.process options*+> will copy class options and set options in
- % all the active families in which the options are found.
- .process options={
- \skv@handlerswafalse\dirkeys@processoptions
+ {.process options,.processoptions,.process options in one family}={
+ \dirkeys@processoptions{}{}
},
- .process options*={
- \skv@handlerswatrue\dirkeys@processoptions
+ {.process options*,.processoptions*,
+ .copy class options and process options,
+ .copy class options and process options in one family}={
+ \dirkeys@processoptions{*}{}
},
- .process options+={
- \skv@handlerswafalse\dirkeys@processoptions@b
+ {.process options+,.processoptions+,.process options in all families}={
+ \dirkeys@processoptions{}{+}
},
- .process options*+={
- \skv@handlerswatrue\dirkeys@processoptions@b
+ {.process options*+,.processoptions*+,
+ .copy class options and process options in all families}={
+ \dirkeys@processoptions{*}{+}
},
% The handler <.mega process options> will:
- % 1. Search all families in its key <families>.
- % 2. Not perform filtering of ignored paths and keys; in fact, will not
+ % 1. Search all families in its key <paths>.
+ % 2. Not filter ignored paths and keys; in fact, it will not
% use active paths and keys.
% 3. The handler '.mega process options' has the keys <ignore options>,
% <options prefix>, <options families>, and <copy class options>.
% These keys have aliases.
% See an example later in this file.
- .mega process options={
+ {.mega process options,.megaprocessoptions}={
\dirkeys@megaprocessoptions{#1}
},
- .mega process options*={
+ {.mega process options*,.megaprocessoptions*}={
\dirkeys@megaprocessoptions{#1,copy class options}
},
},
.handler let={
- .action for unknown option=.action for unknown options,
- .every unknown option=.action for unknown options,
- .define options=.declare options,
- .processoptions=.process options,
- .processoptions*=.process options*,
- .copy class options and process options in all active families=
- .process options*+,
- .copy class options and process options in all families=
- .process options*+,
- .copy class options and process options=.process options*,
- .executeoptions=.execute options,
+ {.action for unknown option,.every unknown option}=
+ .action for unknown options,
},
}
%\skvshowcs{dirkeys@handler@.every unknown option}
@@ -819,69 +898,59 @@
% till after the options section:
\skvrobustdef*\skvafterprocessoptions{%
\expandafter\skvgappendtomacro
- \csname skv@\@currname @\@currext @afterprocess@hook\endcsname
+ \csname skv@\@currname.\@currext @afterprocess@hook\endcsname
}
-\skvnewlet\skvifpackageloaded\@ifpackageloaded
+\skvnewlet\skvifpackageloadedTF\@ifpackageloaded
-\def\skv@visiteduseoptions{01}
-\skvrobustdef*\skv@useoption#1{%
- \if\skv@visiteduseoptions\else
- \skvcsvnormalize\@unusedoptionlist
- \def\skv@visiteduseoptions{00}%
- \fi
- \begingroup
- \@onelevel@sanitize\@unusedoptionlist
- \skv@kvosplit{\detokenize{#1}}{%
- \edef\CurrentOption{\skvtrimspace{##1}}%
+\skvnewdef*\skv@visiteduseoptions{01}
+\skvrobustdef*\skv@removeoption#1{%
+ \ifx\@unusedoptionlist\@empty\else
+ \if\skv@visiteduseoptions\else
+ \skvcsvnormalize\@unusedoptionlist
+ \def\skv@visiteduseoptions{00}%
+ \fi
+ \begingroup
+ \skv@g@tkeyname#1=\skv@getname@nil\skv@tempb
+ \@onelevel@sanitize\skv@tempb
\def\skv@tempa{}%
\skvcommaloop*\@unusedoptionlist\skv@prova{%
- \skv@kvosplit\skv@prova{%
- \edef\reserved@a{\skvtrimspace{####1}}%
- \ifx\reserved@a\CurrentOption\else
- \edef\skv@tempa{%
- \skv@tempa\ifx\skv@tempa\@empty\else,\fi\skv@prova
- }%
- \fi
- }%
+ \expandafter\skv@g@tkeyname\skv@prova=\skv@getname@nil\skv@provb
+ \@onelevel@sanitize\skv@provb
+ \ifx\skv@provb\skv@tempb\else
+ \edef\skv@tempa{\skvaddlist,\skv@tempa\skvexpandonce\skv@prova}%
+ \fi
}%
\let\@unusedoptionlist\skv@tempa
- }%
- \skvaftergroupdef\@unusedoptionlist\endgroup
+ \skvaftergroupdef\@unusedoptionlist\endgroup
+ \fi
}
\skvonlypreamble{%
- \skvdeclareoption,\skvexecuteoptions,\skvprocessoptions,\skv@useoption,
- \dirkeys@declareoptions@a,\dirkeys@declareoptions@b,
- \dirkeys@megaprocessoptions,\dirkeys@processoptions,
- \dirkeys@processoptions@b,\skvprocessoptionswithclassoptions,
- \skvprocessoptionswithoutclassoptions,\dirkeys@executeoptions,
- \dirkeys@executeoptions@b
+ \skvdeclareoption,\skvexecuteoptions,\skvprocessoptions,\skv@removeoption,
+ \skveveryunknownoption,\dirkeys@declareoptions,
+ \dirkeys@megaprocessoptions,\dirkeys@processoptions,\dirkeys@executeoptions,
+ \skvprocessoptionswithclassoptions,\skvprocessoptionswithoutclassoptions
}
%+++++++++++++++++ This package's options section ++++++++++++++++++%
\skvrobustdef*\setupskeyval{\skvsetkeys[SKV]{skeyval}}
\skv@inoptionsectrue
-
-%\skvshowcs{dirkeys@handler@.every unknown option}
-
\directkeys*{%
.every unknown option={
\@onelevel@sanitize\CurrentOption
\PackageWarning{skeyval}{Unknown option '\CurrentOption' ignored}%
},
- .prefix=SKV,
- .family=skeyval,
+ .path=SKV/skeyval,
.holder prefix=skv@,
.new options={
- .bool/verbose/true,
- .bool/tracingkeys/true,
+ .bool/{verbose,tracingkeys}/true,
.ord/{keyparser,key parser}/{,}/
\def\skv@keyparser{#1}%
\skvstripouterbraces{2}\skv@keyparser,
.bool/compatibility/true/
\ifskv@compatibility
\skvafterprocessoptions{%
- \skvifpackageloaded{skeyval-bc}{}{%
+ \skvifpackageloadedTF{skeyval-bc}{}{%
\RequirePackage{skeyval-bc}%
}
}%
@@ -898,9 +967,17 @@
.copy class options,
},
}
-%\skvshowcs{SKV/skeyval/keyparser.@cbk}
-
\skv@inoptionsecfalse
\skv@restorecodes
\endinput
+
+
+
+
+
+
+\edef\skv@prova{\@currname.\@currext/\skvcurrentkey}%
+ \skvxifinTF{,\skv@prova,}{,\skvpackagelist,}{}{%
+ \edef\skvpackagelist{\skvaddlist,\skvpackagelist\skv@prova}%
+ }%