diff options
Diffstat (limited to 'Master/texmf-dist/tex/latex/skeyval/skeyval-core.tex')
-rw-r--r-- | Master/texmf-dist/tex/latex/skeyval/skeyval-core.tex | 2771 |
1 files changed, 1748 insertions, 1023 deletions
diff --git a/Master/texmf-dist/tex/latex/skeyval/skeyval-core.tex b/Master/texmf-dist/tex/latex/skeyval/skeyval-core.tex index 13e0a2a37f2..83348e842a8 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.1, 2012/10/15. % +% This is file 'skeyval-core.tex', version 1.1a, 2012/10/16. % % % % This package and accompanying files may be distributed and/or % % modified under the conditions of the LaTeX Project Public License, % @@ -29,9 +29,6 @@ \csname skeyval-core-loaded\endcsname \expandafter\let\csname skeyval-core-loaded\endcsname\endinput -% Remove ++++++++++++++++++++++++++++++++++++++++++ -\RequirePackage[notraceifs]{codetrace} - \begingroup \catcode035 06 % # \catcode064 11 % @ @@ -45,9 +42,17 @@ \expandafter\do \fi }% - \edef\skv@core@restorecodes{\do035,064,123,125,061,059,\do,}% + \edef\skv@core@restorecodes{\do35,64,123,125,61,59,13,\do,}% } \skv@prova + +\edef\skv@core@restorecodes{% + \unexpanded\expandafter{\skv@core@restorecodes}% + \endlinechar\the\endlinechar\relax + \catcode`\^^M=\the\catcode`\^^M\relax +} +\endlinechar13 % +\catcode013 05 % ^^M \catcode035 06 % # \catcode064 11 % @ \catcode123 01 % { @@ -57,7 +62,7 @@ \def\do#1=#2,{% \ifx\do#1\else \edef\skv@core@restorecodes{% - \skv@core@restorecodes + \unexpanded\expandafter{\skv@core@restorecodes}% \catcode#1=\the\catcode#1\relax }% \catcode#1=#2\relax @@ -65,27 +70,31 @@ \fi } \do 032=10,033=12,036=03,038=04,040=12,041=12,042=12,043=12,% - 059=12,045=12,047=12,058=12,063=12,091=12,093=12,126=13,\do=,% + 059=12,045=12,047=12,058=12,063=12,091=12,093=12,126=13,13=5,\do=,% \newdimen\skvz@\skvz@=0pt\relax +\newcount\skvm@ne\skvm@ne=-1\relax \ifcase - \ifx\eTeXversion\@undefined\skvz@\else - \ifnum\eTeXversion<\tw@\skvz@\else\@ne\fi\fi - \errhelp{This package requires eTeX version 2 or higher.}% + \ifx\eTeXversion\@undefined0\else + \ifnum\eTeXversion<\tw@0\else1\fi\fi\relax + \errhelp{This package requires eTeX version 2 or higher.} \errmessage{skeyval package: eTeX not loaded or old version.} \expandafter\endinput \fi -\newif\ifskv@inlatex +%\chardef\skv@five=5\relax +%\chardef\skv@six=6\relax +\newif\ifskv@latex +\newif\ifskv@tempst \ifx\ProvidesFile\@undefined - \skv@inlatexfalse - \message{File 'skeyval-core.tex' 2012/10/15 v1.1: + \skv@latexfalse + \message{File 'skeyval-core.tex' 2012/10/16 v1.1a: Core of 'skeyval' key-value parser (AM)} \input skeyval-ltxcmds \else - \skv@inlatextrue + \skv@latextrue \ProvidesFile{skeyval-core.tex} - [2012/10/15 v1.1 Base file of skeyval package (AM)] + [2012/10/16 v1.1a Base file of skeyval package (AM)] \@addtofilelist{skeyval-core.tex} \long\def\@nodocument#1{% \@latex@error{'#1' appeared\on@line\space without @@ -216,7 +225,43 @@ {#1}{\unexpanded{#3}}% } -\long\def\skvgobbleldspaces{\skvifnextchar x{}{}} +% Expandable \@testopt: +% +% Eg, +% \def\macroa{\skvnewxtestopt\macrob{Mr.}} +% \def\macrob[#1]#2{#1 #2} +% \edef\testa{\expandafter\macroa\activespace{David Carlisle}} +% \edef\testb{\macroa[Mr.]{Heiko Oberdiek}} +% +\long\def\skvnewxtestopt#1#2#3{% + % #3 will be seen as a space only if that space is active. But + % \skvifstrcmpTF will detokenize that space before comparison. + \skvifstrcmpTF{ }{#3}{% + \skvnewxtestopt#1{#2}% + }{% + \skvifstrcmpTF{#3}{[}% + {#1[}{\skvifntypeTF{#3}{#1[#2]#3}{#1[#2]{#3}}}% + }% +} + +% Expandable \@ifnextchar: +% +% Eg, +% \def\temp{\skvxifnextchar*{\def\x{T}}{\def\x{F}}} +% \temp* (star seen) or \temp<some token> (star not seen) +% +% ** This can't be used to test the presence of explicit left brace. +% +\long\def\skvxifnextchar#1#2#3#4{% + % #4 will be seen as a space only if that space is active. But + % \skvifstrcmpTF will detokenize that space before comparison. + \skvifstrcmpTF{ }{#4}{% + \skvxifnextchar#1{#2}{#3}% + }{% + \skvifstrcmpTF{#4}{#1}{#2}{\skvifntypeTF{#4}{#3#4}{#3{#4}}}% + }% +} + \long\def\skvgobbleleadingspaces{\skvsimpleifnextchar x{}{}} \long\protected\def\skvstarorlong#1{% \skvifstar{\let\l@ngrel@x\relax#1}{\let\l@ngrel@x\long#1}% @@ -272,6 +317,8 @@ \skvnewlet\skv@nil\relax \skvnewlet\skvrelax\relax \skvnewdef*\skv@relaxtoks{\relax} +\skvnewdef*\skv@truetoks{true} +\skvnewdef*\skv@falsetoks{false} \skvnewdef*\skv@nnil{\skv@nil} \skvnewdef\skv@car#1#2\car@nil{#1} \skvnewdef\skv@car@detok#1#2\car@nil{\detokenize{#1}} @@ -285,6 +332,7 @@ \skvnewdef*\skv@quark{\@gobble\skv@quark} \skvnewlet\skvrom\romannumeral \skvnewdef*\skv@rej{^skv^} +\skvnewdef*\skv@dotna{.na} \skvnewdef\skvafterfi#1\fi{\fi#1} \skvnewdef\skvafterfifi@inneriscond#1\fi#2\fi{\fi#1\fi} \skvnewdef\skvafterfifi#1\fi#2\fi{\fi\fi#1} @@ -303,22 +351,22 @@ \in@@#2{\in@@}#1\in@@ } \skvrobustdef*\skvcsnewif#1{% - \skvifstrcmp{#1}{x}{% + \skvifstrcmpTF{#1}{x}{% \skv@err{Redefining primitve '\@backslashchar ifx'?}\@ehd }{% \csname newif\expandafter\endcsname\csname if#1\endcsname }% } \skvnewdef*\skv@zapornot#1{% - \ifnum#1=\skvz@ - \expandafter\@iden - \else + \if#1% \expandafter\skvzapspaces + \else + \expandafter\@iden \fi } \skvnewdef\skvzapspaces#1{\skv@zapspaces.#1 \zap@nil} \skvnewdef\skv@zapspaces#1 #2\zap@nil{% - \skvifblank{#2}{% + \skvifblankTF{#2}{% \@gobble#1% }{% \skv@zapspaces#1#2\zap@nil @@ -331,26 +379,26 @@ \newcommand\skvifleadspace[3]{% \romannumeral\csname - @\skvifnull{#1}{second}{\iffalse{\fi\skv@ifleadspace.#1 x}}% + @\skvifnullTF{#1}{second}{\iffalse{\fi\skv@ifleadspace.#1 x}}% oftwo\endcsname{0 #2}{0 #3}% } \skvnewdef\skv@ifleadspace#1 {% - \expandafter\skvifnull\expandafter{\@gobble#1}{first}{second}% + \expandafter\skvifnullTF\expandafter{\@gobble#1}{first}{second}% \expandafter\@gobble\expandafter{\iffalse}\fi } -% \skvifldspace{ }{}{} gives <true> as desired. +% \skvifldspaceTF{ }{}{} gives <true> as desired. \begingroup \lccode`\&=0 \catcode`\&=7 \lccode`\!=0 \catcode`\!=8 \lowercase{\endgroup - \skvnewdef\skvifldspace#1{\skv@ifldspace!#1! &} - \skvnewdef\skv@ifldspace#1! #2&{\skvifnotblank{#2}} + \skvnewdef\skvifldspaceTF#1{\skv@ifldspace!#1! &} + \skvnewdef\skv@ifldspace#1! #2&{\skvifblankFT{#2}} \skvnewdef\skvtrimspace#1{\skv@trimspace@a.#1& &} \skvnewdef\skv@trimspace@a#1 &{\skv@trimspace@b#1&} \skvnewdef\skv@trimspace@b#1{% \unexpanded\expandafter{% \romannumeral0% - \expandafter\skvifldspace\expandafter{\@gobble#1}{% + \expandafter\skvifldspaceTF\expandafter{\@gobble#1}{% \@gobble#1% }{% \expandafter\@space\@gobble#1% @@ -364,7 +412,7 @@ \edef#1{\expandafter\skvtrimspace\expandafter{#1}}% } \skvnewdef*\skvcsuse#1{% - \ifcsname#1\endcsname + \skvifcsname#1\then \csname#1\expandafter\endcsname \fi } @@ -375,12 +423,17 @@ \skvnewdef\skvaftercsname#1#2{% \expandafter\skvswap\expandafter{\csname#2\endcsname}{#1}% } -\skvnewdef*\skvifdef#1{% - \skvifblank{#1}\@secondoftwo{% - \skvifx#1\@undefined{% +\skvnewlet\skvaftercs\skvaftercsname +\skvnewdef*\skvifdef#1\then{\if0\skvifdefTF{#1}{0}{1}} +\skvnewdef*\skvifundef#1\then{\if0\skvifdefTF{#1}{1}{0}} +% \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#1\relax + \ifx\relax#1% \expandafter\@secondoftwo \else \expandafter\@firstoftwo @@ -388,9 +441,9 @@ }% }% } -\skvnewdef*\skvifundef#1{\skvifdef{#1}\@secondoftwo\@firstoftwo} -\skvnewdef*\skvifcsdef#1{% - \skvifblank{#1}{% +\skvnewdef*\skvifdefFT#1{\skvifdefTF{#1}\@secondoftwo\@firstoftwo} +\skvnewdef*\skvifcsdefTF#1{% + \skvifblankTF{#1}{% \expandafter\@secondoftwo\@gobble }{% \ifcsname#1\endcsname @@ -407,24 +460,25 @@ \fi }% } -\skvnewdef*\skvifcsundef#1{\skvifcsdef{#1}\@secondoftwo\@firstoftwo} +\skvnewdef*\skvifcsdefFT#1{\skvifcsdefTF{#1}\@secondoftwo\@firstoftwo} \def\skv@ifx@#1#2\skv@ifx@nil{\expandafter#1} -\skvnewdef*\skvifx#1#2{% +\def\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@car#2\noboundary\car@nil + \ifx\skv@ifx@#1\batchmode\skv@ifx@nil\skv@ifx@@#2\noboundary\skv@ifx@nil first\else second\fi oftwo\endcsname } -\skvnewdef*\skvnotifx#1#2{\skvifx{#1}{#2}\@secondoftwo\@firstoftwo} +\skvnewdef*\skvifxFT#1#2{\skvifxTF{#1}{#2}\@secondoftwo\@firstoftwo} \skvnewdef*\skv@ghost{\@gobble\skv@ghost} -\skvnewdef\skvifempty#1{% +\skvnewdef\skvifemptyTF#1{% \ifx#1\@empty\skv@ghost \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi } -\skvnewdef\skvifcsempty#1{\expandafter\skvifempty\csname#1\endcsname} -\skvnewdef\skvifdefempty#1{% - \skvifblank{#1}\@secondoftwo{% - \skvifntype{#1}{% - \skvifdef{#1}{\skvifx#1\@empty}{\@secondoftwo}% +\skvnewdef\skvifcsemptyTF#1{\expandafter\skvifemptyTF\csname#1\endcsname} +\skvnewdef\skvifdefemptyTF#1{% + \skvifblankTF{#1}\@secondoftwo{% + \skvifntypeTF{#1}{% + \skvifdefTF{#1}{\skvifxTF#1\@empty}{\@secondoftwo}% }{% \@secondoftwo }% @@ -436,22 +490,21 @@ % Keep lccode, in case the test occurs in a table: \lccode`\&=0 \catcode`\&=8 \lowercase{\endgroup - \skvnewdef\skvifnull#1{% + \skvnewdef\skvifnullTF#1{% \csname @\ifcat&\detokenize{#1}&first\else second\fi oftwo\endcsname } \skvnewdef\skviflacus#1\then{\ifcat&\detokenize{#1}&} } -\skvnewdef\skvifblank#1{% - \expandafter\skvifnull\expandafter{\@gobble#1.}% +\skvnewdef\skvifblankTF#1{% + \expandafter\skvifnullTF\expandafter{\@gobble#1.}% } -\skvnewdef\skvifnotblank#1{\skvifblank{#1}\@secondoftwo\@firstoftwo} -\skvnewdef\iflacuna#1\then{\if\relax\detokenize{#1}\relax} +\skvnewdef\skvifblankFT#1{\skvifblankTF{#1}\@secondoftwo\@firstoftwo} -\skvnewdef*\skvifbool#1{% - \skvifblank{#1}{% +\skvnewdef*\skvifboolTF#1{% + \skvifblankTF{#1}{% \@secondoftwo }{% - \skvifcsdef{if#1}{% + \skvifcsdefTF{if#1}{% \csname @\csname if#1\endcsname first\else second\fi oftwo\endcsname }{% @@ -459,35 +512,33 @@ }% }% } -\skvnewdef*\skvifnotbool#1{\skvifbool{#1}\@secondoftwo\@firstoftwo} -\skvnewdef*\skvifbooltrue#1\then{\csname if#1\endcsname} -\skvnewdef*\skvifboolfalse#1\then{\csname if#1\endcsname\else} -\skvnewdef*\skvifdefbool#1{% +\skvnewdef*\skvifboolFT#1{\skvifboolTF{#1}\@secondoftwo\@firstoftwo} +% \skvifbool sw1\then <true> \else <false> \fi +\skvnewdef*\skvifbool#1\then{\if0\skvifboolTF{#1}01} +\skvnewdef*\skvifdefboolTF#1{% \csname @\csname if#1\endcsname first\else second\fi oftwo\endcsname } -% \skvlogicalif<bool>"<true>"<false>" -\skvnewdef*\skvlogicalif#1"#2"#3"{% - \skvifbool{#1}{#2}{#3}\skvgobbleleadingspaces -} -% \skvifboolval{<toks>}{<true>}{<false>} -\skvrobustdef*\skvifboolval#1{% - \skvxifin{,\expandafter\skvtrimspace\expandafter +\skvnewdef*\skvifdefboolFT#1{\skvifdefboolTF{#1}\@secondoftwo\@firstoftwo} +% \skvifboolvalTF{<toks>}{<true>}{<false>} +\skvrobustdef*\skvifboolvalTF#1{% + \skvxifinTF{,\expandafter\skvtrimspace\expandafter {\detokenize{#1}},}{,\detokenize{true,false},}% } +\skvrobustdef*\skvxifboolvalTF#1{% + \begingroup + \edef\skv@prova{#1}% + \skvdespacecontent\skv@prova + \skvexpandtwoargs{\endgroup\skvifinTF} + {,\skvoxdetok\skv@prova,}{,\detokenize{true,false},}% +} % Generate error if <toks> is not a valid boolean value, otherwise % execute #2: -% \skvifvalidboolval{<toks>}{<true>} -\skvrobustdef*\skvifvalidboolval#1#2{% - \skvxifin{,\expandafter\skvtrimspace\expandafter +% \skvifboolvalT{<toks>}{<true>} +\skvrobustdef*\skvifboolvalT#1#2{% + \skvxifinTF{,\expandafter\skvtrimspace\expandafter {\detokenize{#1}},}{,\detokenize{true,false},}% {#2}{\skv@badboolerr{#1}}% } -\skvrobustdef*\skvxifboolval#1{% - \begingroup - \edef\skv@prova{#1}% - \skvexpandtwoargs{\endgroup\skvifin} - {,\skvoxdetok\skv@prova,}{,\detokenize{true,false},}% -} % Convert bool value (true or false) to switch value (00 or 01): \skvrobustdef*\skvbooltoswitch#1#2{% \begingroup @@ -505,74 +556,116 @@ \skv@err{Invalid boolean value '#1'; expected 'true' or 'false'}\@ehd } -% All switch functions of skeyval pacakge operate on a command -% and not on csname. -\skvnewdef*\skvnewswitch#1{% - \skvifcsdef{skv@sw@#1}{% +% Switches and toggles have separate namespaces. +\skvrobustdef*\skvnewswitch#1{% + \skvifcsdefTF{skv@switch@#1}{% \skv@err{Switch '\detokenize{#1}' already exists}\@ehd }{% - \skvcsdef{skv@sw@#1}{01}% + \skvcsdef{skv@switch@#1}{01}% }% } -\skvnewdef*\skvifswitch#1{% +\skvnewdef*\skvifswitchTF#1{% \if - \skvifcsdef{skv@sw@#1}{% - \csname skv@sw@#1\endcsname - \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi + \skvifcsdefTF{skv@switch@#1}{% + \csname skv@switch@#1\endcsname }{% 01% }% + \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi +} +\skvnewdef*\skvifdefswitchTF#1{% + \if\csname skv@switch@#1\endcsname + \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi } -\skvnewdef*\skvswitchtrue#1{% - \skvifcsdef{skv@sw@#1}{% - \skvcsdef{skv@sw@#1}{00}% +\skvrobustdef*\skvswitchtrue#1{% + \skvifcsdefTF{skv@switch@#1}{% + \skvcsdef{skv@switch@#1}{00}% }{% \skv@err{No switch '\detokenize{#1}'}\@ehd }% } -\skvnewdef*\skvswitchfalse#1{% - \skvifcsdef{skv@sw@#1}{% - \skvcsdef{skv@sw@#1}{01}% +\skvrobustdef*\skvswitchfalse#1{% + \skvifcsdefTF{skv@switch@#1}{% + \skvcsdef{skv@switch@#1}{01}% }{% \skv@err{No switch '\detokenize{#1}'}\@ehd }% } - -\begingroup -\def\x#1{\endgroup - \skvnewdef*\skvnegatesw##1{% - 0\ifcase##11#1\or\expandafter1\else\expandafter0\fi +\skvrobustdef*\skvnewtog#1{% + \skvifcsdefTF{skv@toggle@#1}{% + \skv@err{Switch '\detokenize{#1}' already exists}\@ehd + }{% + \skvcslet{skv@toggle@#1}\@secondoftwo }% - \skvnewdef*\skvifbothswtrue##1##2{% - 0\ifcase##1##2#1\expandafter0\else\expandafter1\fi +} +\skvrobustdef*\skvdeftog#1{\skvcslet{skv@toggle@#1}\@secondoftwo} +\skvnewdef*\skviftogTF#1{% + \skvifcsdefTF{skv@toggle@#1}{% + \csname skv@toggle@#1\endcsname + }{% + \@secondoftwo + }% +} +\skvnewdef*\skviftogFT#1{\skviftogTF{#1}\@secondoftwo\@firstoftwo} +\skvnewdef*\skvifdeftogTF#1{\csname skv@toggle@#1\endcsname} +\skvrobustdef*\skvsettogtrue#1{% + \skvifcsdefTF{skv@toggle@#1}{% + \skvcslet{skv@toggle@#1}\@firstoftwo + }{% + \skv@err{No toggle '\detokenize{#1}'}\@ehd }% - \skvnewdef*\skvifoneswtrue##1##2{% - 0\ifnum##1##2<101#1\expandafter0\else\expandafter1\fi +} +\skvrobustdef*\skvsettogfalse#1{% + \skvifcsdefTF{skv@toggle@#1}{% + \skvcslet{skv@toggle@#1}\@secondoftwo + }{% + \skv@err{No toggle '\detokenize{#1}'}\@ehd }% } -\x{ } -\skvnewdef\skvifcond#1\fi{% +% plasw=plain switch (ie, 00 or 01). +\skvnewdef*\skvifplaswTF#1{% + \if#1\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi +} +\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 } -\skvnewdef\skvifnotcond#1\fi{\skvifcond{#1}\fi\@secondoftwo\@firstoftwo} -% Maybe #1 isn't expandable: -\skvnewdef\skvifcondition#1\fi{% +\skvnewdef\skvifcondFT#1\fi{\skvifcondTF{#1}\fi\@secondoftwo\@firstoftwo} +% In case #1 isn't expandable. This is the difference between +% \skvifcondTF and \skvifconditionTF. +\skvnewdef\skvifconditionTF#1\fi{% #1\relax \expandafter\@firstoftwo \else \expandafter\@secondoftwo \fi } -\skvnewdef*\skvifnum#1#{\skvifcond\ifnum#1\fi} +\skvnewdef*\skvifnumTF#1#{\skvifcondTF\ifnum#1\fi} +\skvnewdef*\skvifdim#1#{\skvifcondTF\ifdim#1\fi} +\skvnewdef*\skvifnumFT#1#{\skvifnumTF#1{\@secondoftwo}{\@firstoftwo}} \skvnewdef\skvalloftwo#1#2{#1#2} % If '#1' is a single, non-space and non-braced token: -\skvnewdef\skvifntype#1{% +\skvnewdef\skvifntypeTF#1{% \csname @\if0\skv@strcmp {\skvexpandonce{\skvalloftwo#1{}{}}}{\unexpanded{#1{}}}% first\else second\fi oftwo\endcsname } -\skvnewdef\skvxifntype{\skvexpandarg\skvifntype} +\skvnewdef\skvxifntypeTF{\skvexpandarg\skvifntypeTF} \skvrobustdef*\skvundef#1{\let#1\@undefined} \skvrobustdef*\skvgundef#1{\global\let#1\@undefined} \skvrobustdef*\skvcsundef#1{\skvcslet{#1}\@undefined} @@ -583,38 +676,45 @@ \skvrobustdef*\skvemptifycmds#1{% \skvcommaparse{#1}\skv@prova{\expandafter\def\skv@prova{}}% } -\skvifdef\pdfstrcmp{% +\skvrobustdef*\skvemptify#1{\def\do##1{\def##1{}}#1} +\skvrobustdef*\skvdumpgarbage{% + \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 }{% \RequirePackage{pdftexcmds}% - \skvifdef\pdf@strcmp{% + \skvifdefTF\pdf@strcmp{% \let\skv@strcmp\pdf@strcmp }{% \skv@err{Neither '\string\pdfstrcmp' nor '\string\pdf@strcmp' exists}\@ehd }% } -\skvnewdef\skvifstrcmp#1#2{% +\skvnewdef\skvifstrcmpTF#1#2{% \csname @\ifnum\skv@strcmp{\detokenize{#1}}% {\detokenize{#2}}=0first\else second\fi oftwo\endcsname } -\skvnewdef\skvifstreq#1\with#2\then{% +\skvnewdef*\skvifstrcmpFT#1#2{\skvifstrcmpTF{#1}{#2}\@secondoftwo\@firstoftwo} +\skvnewdef\skvifstreq#1#2\then{% \ifnum\skv@strcmp{\detokenize{#1}}{\detokenize{#2}}=\skvz@ } -% \ifskvstreq may be used in, eg, \newforeach, where every user-given -% conditional must start with \if...: -\skvnewlet\ifskvstreq\skvifstreq -\skvnewdef\skvoifstrcmp#1#2{% +\skvnewdef\skvoifstrcmpTF#1#2{% \csname @\ifnum\skv@strcmp{\skvexpandonce{#1}}% {\skvexpandonce{#2}}=0first\else second\fi oftwo\endcsname } -\skvnewdef\skvxifstrcmp#1#2{% +\skvnewdef\skvxifstrcmpTF#1#2{% \csname @\ifnum\skv@strcmp{#1}{#2}=0first\else second\fi oftwo\endcsname } \skvrobustdef\skvcslet#1#2{\expandafter\let\csname#1\endcsname#2} \skvrobustdef\skvnewcslet#1{% - \skvifcsdef{#1}{% + \skvifcsdefTF{#1}{% \skv@err{Command '\skvnoexpandcs{#1}' already defined}\@ehd }{% \skvcslet{#1}% @@ -625,7 +725,7 @@ \let\expandafter#1\csname#2\endcsname } \skvrobustdef\skvnewletcs#1{% - \skvifdef{#1}{% + \skvifdefTF{#1}{% \skv@err{Command '\string#1' already defined}\@ehd }{% \skvletcs#1% @@ -637,7 +737,7 @@ \endcsname\csname#2\endcsname } \skvrobustdef\skvnewcsletcs#1{% - \skvifcsdef{#1}{% + \skvifcsdefTF{#1}{% \skv@err{Command '\skvnoexpandcs{#1}' already defined}\@ehd }{% \skvcsletcs{#1}% @@ -694,8 +794,8 @@ \skvrobustdef*\skvsetnumber#1{% \begingroup - \def#1{\edef#1{\endgroup\def\noexpand#1{\the\count@}}#1}% - \afterassignment#1\count@ + \def\x{\edef\x{\endgroup\def\noexpand#1{\the\count@}}\x}% + \afterassignment\x\count@ } \skvnewlet\skvsetno\skvsetnumber \skvrobustdef*\skvadvanceno{\skv@advanceno\relax} @@ -705,21 +805,21 @@ \begingroup \count@#3\relax \endgroup - \skvifdef#2{% + \skvifdefTF#2{% #1\edef#2{\the\numexpr#2+#3\relax}% }{% \skv@err{Number '\string#2' is not defined}\@ehd }% } \skvrobustdef*\skvpushnumber#1{% - \skvifdef#1{% + \skvifdefTF#1{% \edef#1{\the\numexpr#1+1\relax}% }{% \def#1{0}% }% } \skvrobustdef*\skvpopnumber#1{% - \skvifdef#1{% + \skvifdefTF#1{% \edef#1{\the\numexpr#1+1\relax}% }{% \skv@err{Number '\string#1' is not defined}\@ehd @@ -736,11 +836,11 @@ % Removing spurious spaces before checking for brace. -% If we were to use \skvtrimspace for \skvifbraced, then the need +% If we were to use \skvtrimspace for \skvifbracedTF, then the need % for double \romannumeral will cause problems of premature expansion. \begingroup \lccode`\&=0 \catcode`\&=7 -\skvnewgdef\skvifbraced#1{% +\skvnewgdef\skvifbracedTF#1{% \expandafter\skv@ifbraced@a\expandafter{% \romannumeral-`\q\skv@ifbraced@b.#1& &% }% @@ -748,15 +848,15 @@ \skvnewgdef\skv@ifbraced@a#1{\skv@ifbraced@d#1\brace@nil{#1}} \skvnewgdef\skv@ifbraced@b#1 &{\skv@ifbraced@c#1&} \skvnewgdef\skv@ifbraced@c#1{% - \expandafter\skvifldspace\expandafter{\@gobble#1}% + \expandafter\skvifldspaceTF\expandafter{\@gobble#1}% {\@gobble#1}{\expandafter\@space\@gobble#1}% } \skvnewgdef\skv@ifbraced@d#1\brace@nil#2{% - \skvifstrcmp{#1}{#2}\@secondoftwo\@firstoftwo + \skvifstrcmpTF{#1}{#2}\@secondoftwo\@firstoftwo } \endgroup -\skvnewdef\skvifnotbraced#1{\skvifbraced{#1}\@secondoftwo\@firstoftwo} +\skvnewdef\skvifbracedFT#1{\skvifbracedTF{#1}\@secondoftwo\@firstoftwo} % \skvstripouterbraces{<nr>}<cmd> \skvrobustdef*\skvstripouterbraces#1#2{% @@ -766,7 +866,7 @@ } \skvrobustdef*\skv@stripouterbraces#1\strip@nil#2#3{% \advance\@tempcnta\@ne - \skvifnum\@tempcnta=#3{% + \skvifnumTF\@tempcnta=#3{% \edef#2{\unexpanded{#1}}% \skvaftergroupdef#2\endgroup }{% @@ -774,19 +874,19 @@ }% } -\skvrobustdef*\skvifescaped#1{% +\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{\skvifescaped{#1}\@secondoftwo\@firstoftwo} +\skvnewdef\skvifnotescaped#1{\skvifescapedTF{#1}\@secondoftwo\@firstoftwo} \skvnewdef*\skvremovescape#1{\expandafter\@gobble\string#1} \skvnewdef*\skvgobblescape#1{% - \skvifblank{#1}{}{% - \skvifnum\escapechar>255{\string#1}{% - \skvifnum\escapechar<0{\string#1}{% - \skvifnum\escapechar=32{% + \skvifblankTF{#1}{}{% + \skvifnumTF\escapechar>255{\string#1}{% + \skvifnumTF\escapechar<0{\string#1}{% + \skvifnumTF\escapechar=32{% \expandafter\@gobblespace\string#1% }{% \skvremovescape{#1}% @@ -828,15 +928,15 @@ \expandafter\skvswap\expandafter{\expandafter{#2}}{#1}% } \skvnewlet\skvexpbracenext\skvexpandbracenext -\skvrobustdef*\skvifin#1#2{% +\skvrobustdef*\skvifinTF#1#2{% \skv@in@{#1}{#2}% \csname @\ifin@ first\else second\fi oftwo\endcsname } -\skvrobustdef*\skvifnotin#1#2{\skvifin{#1}{#2}\@secondoftwo\@firstoftwo} -\skvrobustdef*\skvxifin#1#2{\skvexpandtwoargs\skvifin{#1}{#2}} -\skvrobustdef*\skvxifnotin#1#2{\skvxifin{#1}{#2}\@secondoftwo\@firstoftwo} -\skvrobustdef*\skvifindetok#1#2#3{% - \skvexpandtwoargs\skvifin{#1\skvoxdetok{#2}#1}{#1\skvoxdetok{#3}#1}% +\skvrobustdef*\skvifinFT#1#2{\skvifinTF{#1}{#2}\@secondoftwo\@firstoftwo} +\skvrobustdef*\skvxifinTF#1#2{\skvexpandtwoargs\skvifinTF{#1}{#2}} +\skvrobustdef*\skvxifinFT#1#2{\skvxifinTF{#1}{#2}\@secondoftwo\@firstoftwo} +\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@} @@ -849,6 +949,7 @@ }% \skv@tempa#1==\skv@kvsplit } +\skvrobustdef*\skv@kvosplit#1{\skvexpbracenext\skv@kvsplit{#1}} % \skv@slsplit{<slashlist>}{<parametered.callback>} \skvrobustdef*\skv@slsplit#1#2{% \begingroup @@ -857,6 +958,8 @@ }% \skv@tempa#1/^skv^/^skv^/^skv^/^skv^/^skv^/^skv^/^skv^/\skv@slsplit } +\skvnewlet\skv@slashsplit\skv@slsplit +\skvrobustdef*\skv@slosplit#1{\skvexpbracenext\skv@slsplit{#1}} \skvrobustdef*\skv@rescan#1{% \begingroup @@ -869,15 +972,15 @@ \expandafter\reserved@a\scantokens\expandafter{#1}% } -\skvnewdef*\skvifdigitpresent#1{% - \skvifcond\if0\skvifblank{#1}{1}{\skv@ifdigitpresent#1\skv@nnil}\fi +\skvnewdef*\skvifdigitpresentTF#1{% + \skvifcondTF\if0\skvifblankTF{#1}{1}{\skv@ifdigitpresent#1\skv@nnil}\fi } \skvnewdef*\skv@ifdigitpresent#1{% - \skvifx#1\skv@nnil{% + \skvifxTF#1\skv@nnil{% 1% }{% - \skvifnum`#1>47{% - \skvifnum`#1<58{% + \skvifnumTF`#1>47{% + \skvifnumTF`#1<58{% 0\skv@removetonnil }{% \skv@ifdigitpresent @@ -888,13 +991,13 @@ }% } -\skvnewdef*\skvifalldigit#1{% - \skvifcond\if0\skvifblank{#1}{1}{\skv@ifalldigit#1\skv@nnil}\fi +\skvnewdef*\skvifalldigitTF#1{% + \skvifcondTF\if0\skvifblankTF{#1}{1}{\skv@ifalldigit#1\skv@nnil}\fi } \skvnewdef*\skv@ifalldigit#1{% - \skvifx#1\skv@nnil{0}{% - \skvifnum`#1>47{% - \skvifnum`#1<58{% + \skvifxTF#1\skv@nnil{0}{% + \skvifnumTF`#1>47{% + \skvifnumTF`#1<58{% \skv@ifalldigit }{% 1\skv@removetonnil @@ -905,15 +1008,15 @@ }% } -\skvnewdef*\skvifalphapresent#1{% - \skvifcond\if0\skvifblank{#1}{1}{\skv@ifalphapresent#1\skv@nnil}\fi +\skvnewdef*\skvifalphapresentTF#1{% + \skvifcondTF\if0\skvifblankTF{#1}{1}{\skv@ifalphapresent#1\skv@nnil}\fi } \skvnewdef*\skv@ifalphapresent#1{% - \skvifx#1\skv@nnil{% + \skvifxTF#1\skv@nnil{% 1% }{% - \skvifnum`#1>96{% - \skvifnum`#1<123{% + \skvifnumTF`#1>96{% + \skvifnumTF`#1<123{% 0\skv@removetonnil }{% \skv@ifalphapresent @@ -923,15 +1026,15 @@ }% }% } -\skvnewdef*\skvifAlphapresent#1{% - \skvifcond\if0\skvifblank{#1}{1}{\skv@ifAlphapresent#1\skv@nnil}\fi +\skvnewdef*\skvifAlphapresentTF#1{% + \skvifcondTF\if0\skvifblankTF{#1}{1}{\skv@ifAlphapresent#1\skv@nnil}\fi } \skvnewdef*\skv@ifAlphapresent#1{% - \skvifx#1\skv@nnil{% + \skvifxTF#1\skv@nnil{% 1% }{% - \skvifnum`#1>64{% - \skvifnum`#1<91{% + \skvifnumTF`#1>64{% + \skvifnumTF`#1<91{% 0\skv@removetonnil }{% \skv@ifAlphapresent @@ -941,12 +1044,12 @@ }% }% } -\skvnewdef*\skvifprimitive#1{% +\skvnewdef*\skvifprimitiveTF#1{% \expandafter\skv@ifprimitive\meaning#1\relax } \skvnewdef*\skv@ifprimitive#1#2\relax{% - \skvifcond\if#1\@backslashchar\fi{% - \skvifdigitpresent{#2}\@secondoftwo\@firstoftwo + \skvifcondTF\if#1\@backslashchar\fi{% + \skvifdigitpresentTF{#2}\@secondoftwo\@firstoftwo }{% \@secondoftwo }% @@ -959,13 +1062,13 @@ \def\x##1{\skvnoexpandcs{skv@\skvremovescape#1test@##1}}% \edef\x{\endgroup \def\noexpand#2####1{% - \unexpanded{\skvifx#1{##1}\@secondoftwo}{% - \unexpanded{\skvifprimitive{##1}\@secondoftwo}% + \unexpanded{\skvifxTF#1{##1}\@secondoftwo}{% + \unexpanded{\skvifprimitiveTF{##1}\@secondoftwo}% {\noexpand\expandafter\x{a}\noexpand\meaning####1:&}% }% }% \def\x{a}####1:####2&{\x{b}####1\string#1&}% - \def\x{b}####1\string#1####2&{\noexpand\skvifblank{####1}}% + \def\x{b}####1\string#1####2&{\noexpand\skvifblankTF{####1}}% }\x } \endgroup @@ -983,15 +1086,16 @@ } % If all the tokens are digits or arithmetic: -\skvnewdef*\skvifallarithmetic#1{% +\skvnewdef*\skvifallarithmeticTF#1{% \begingroup \skv@swatrue \skvifdimensionable{#1}{}{% \ifskv@isinteger\else \def\do##1##2{% \ifx\do##1\else - \skvifin{##1}{0123456789.+-*/()}{}{% - \skvifin{,##1##2,}{,em,ex,in,pt,pc,cm,mm,dd,cc,nd,nc,bp,sp,}{}{% + \skvifinTF{##1}{0123456789.+-*/()}{}{% + \skvifinTF{,##1##2,} + {,em,ex,in,pt,pc,cm,mm,dd,cc,nd,nc,bp,sp,}{}{% \skv@swafalse \def\do####1\skvrelax{}% }% @@ -1032,7 +1136,7 @@ \skvnewregister\bool\ifskv@isinteger -% In case the argument of \skvifinteger containes \numexpr: +% In case the argument of \skvifintegerTF containes \numexpr: \skvnewlet\skv@catch@nil\relax % #1: Essence, #2: Test token \skvrobustdef*\skvensureinteger#1#2{% @@ -1050,34 +1154,34 @@ \skvrobustdef*\skv@catchremainder#1\skv@catch@nil{% \endgroup\def\skv@elt{#1}% } -\skvrobustdef*\skvifinteger#1{% +\skvrobustdef*\skvifintegerTF#1{% \begingroup % Don't try '\numexpr0+#1' here: \afterassignment\skv@catchremainder \@tempcnta\numexpr0#1\relax\skv@catch@nil - \skvifx\skv@elt\@empty{% + \skvifxTF\skv@elt\@empty{% \@firstoftwo }{% - \skvifx\skv@elt\skv@relaxtoks\@firstoftwo\@secondoftwo + \skvifxTF\skv@elt\skv@relaxtoks\@firstoftwo\@secondoftwo }% } -\skvrobustdef\skvoifinteger{\skvexpbracenext\skvifinteger} +\skvrobustdef\skvoifinteger{\skvexpbracenext\skvifintegerTF} \skvrobustdef\skvifdimensionable#1{% \def\skv@dimunit{}% % Does 'pt' mean 0pt or 1pt? Make it an invalid input: - \lowercase{\skvifindetok{,}{#1}}\skv@validunit{% + \lowercase{\skvifindetokTF{,}{#1}}\skv@validunit{% \@latexerr{Illegal step '#1': no number found with it}\@ehd }{}% \skv@isintegerfalse - \skvifinteger{#1}{% + \skvifintegerTF{#1}{% \skv@isintegertrue\@secondoftwo }{% \expandafter\skv@ifdimensionable\skv@elt\skv@catch@nil }% } \skvrobustdef\skv@ifdimensionable#1#2\skv@catch@nil{% - \skvifx\relax#1{% - \skvifblank{#2}{% + \skvifxTF\relax#1{% + \skvifblankTF{#2}{% \skv@isintegertrue\@secondoftwo }{% \expandafter\skv@findunit\skv@elt\skv@catch@nil @@ -1098,7 +1202,7 @@ \expandafter\@secondoftwo \fi }% - \skvifstrcmp{.}{#1}{% + \skvifstrcmpTF{.}{#1}{% % In this case, #1 must have come with a trailing \relax. % Remove it and re-start the test: \def\skv@prova##1##2\relax\skv@catch@nil{% @@ -1107,13 +1211,13 @@ \skv@prova#2#3\skv@catch@nil }{% % Check for a valid unit. May be a \dimendef'd token. - \skvifin{,#1,}{,\hsize,\vsize,}{% + \skvifinTF{,#1,}{,\hsize,\vsize,}{% \skv@provb }{% \skvifdimen{#1}{% \skv@provb }{% - \lowercase{\skvifindetok{,}{#1#2}}\skv@validunit{% + \lowercase{\skvifindetokTF{,}{#1#2}}\skv@validunit{% \def\skv@dimunit{#1#2}% % Check if #3 has only one (leading) \relax: \def\skv@prova##1##2##3\skv@catch@nil{% @@ -1167,66 +1271,66 @@ \skv@dimexpr@true\skv@dimexpr@false } \skvrobustdef*\skv@dimexpr@end@end{% - \skvifnum\@tempcnta<\skvz@ + \skvifnumTF\@tempcnta<\skvz@ {\endgroup\@secondoftwo}{\endgroup\@firstoftwo}% } \skvrobustdef*\skv@dimexpr@true{\advance\@tempcnta\skvz@} \skvrobustdef*\skv@dimexpr@false{\advance\@tempcnta\m@ne} \skvrobustdef*\skv@dimexpr@bgroup#1(#2\skv@catch@nil{% \skv@dimexpr@egroup#1)\skv@catch@nil - \skvifblank{#2}{}{% + \skvifblankTF{#2}{}{% \skv@dimexpr@beg \skv@dimexpr@bgroup#2\skv@catch@nil }% } \skvrobustdef*\skv@dimexpr@egroup#1)#2\skv@catch@nil{% \skv@dimexpr@plus#1+\skv@catch@nil - \skvifblank{#2}{}{% + \skvifblankTF{#2}{}{% \skv@dimexpr@end \skv@dimexpr@egroup#2\skv@catch@nil }% } \skvrobustdef*\skv@dimexpr@plus#1+#2\skv@catch@nil{% \skv@dimexpr@minus#1-\skv@catch@nil - \skvifblank{#2}{}{\skv@dimexpr@plus#2\skv@catch@nil}% + \skvifblankTF{#2}{}{\skv@dimexpr@plus#2\skv@catch@nil}% } \skvrobustdef*\skv@dimexpr@minus#1-#2\skv@catch@nil{% - \skvifblank{#1}{}{% - \skvifin{*}{#1}{% - \skvifin{/}{#1}{% + \skvifblankTF{#1}{}{% + \skvifinTF{*}{#1}{% + \skvifinTF{/}{#1}{% \skv@err{I can't parse this: both star (*) and slash \MessageBreak (/) are in '#1'}\@ehd }{% - \skvifblank{#1}{}{\skv@dimexpr@times#1*\skv@catch@nil}% + \skvifblankTF{#1}{}{\skv@dimexpr@times#1*\skv@catch@nil}% }% }{% - \skvifblank{#1}{}{\skv@dimexpr@divide#1/\skv@catch@nil}% + \skvifblankTF{#1}{}{\skv@dimexpr@divide#1/\skv@catch@nil}% }% }% - \skvifblank{#2}{}{\skv@dimexpr@minus#2\skv@catch@nil}% + \skvifblankTF{#2}{}{\skv@dimexpr@minus#2\skv@catch@nil}% } % Because of, eg, 2pt*3/2, the test for * is more subtle: \skvrobustdef*\skv@dimexpr@times#1*#2\skv@catch@nil{% - \skvifblank{#1}{}{% + \skvifblankTF{#1}{}{% \skvifdimensionable{#1}\skv@dimexpr@true\skv@dimexpr@false }% - \skvifblank{#2}{}{% + \skvifblankTF{#2}{}{% \def\skv@prova##1*##2\skv@catch@nil{##1}% \skvexpbracenext\skv@dimexpr@integer{\skv@prova#2\skv@catch@nil}% }% } \skvrobustdef*\skv@dimexpr@divide#1/#2\skv@catch@nil{% - \skvifblank{#1}{}{% + \skvifblankTF{#1}{}{% \skvifdimensionable{#1}\skv@dimexpr@true\skv@dimexpr@false }% - \skvifblank{#2}{}{% + \skvifblankTF{#2}{}{% \def\skv@prova##1/##2\skv@catch@nil{##1}% \skvexpbracenext\skv@dimexpr@integer{\skv@prova#2\skv@catch@nil}% }% } \skvrobustdef*\skv@dimexpr@integer#1{% - \skvifblank{#1}{}{% - \skvifinteger{#1}\skv@dimexpr@true\skv@dimexpr@false + \skvifblankTF{#1}{}{% + \skvifintegerTF{#1}\skv@dimexpr@true\skv@dimexpr@false }% } @@ -1235,7 +1339,7 @@ \begingroup % The following \relax will not be cat-12, so it won't appear in #2: \def\skv@trim@a{% - \skvxifin{\detokenize{#1}\relax}{\skvoxdetok{#2}\relax}{% + \skvxifinTF{\detokenize{#1}\relax}{\skvoxdetok{#2}\relax}{% \def\skv@trim@b####1#1\normal@nil{% \edef#2{\unexpanded{####1}}% \skv@trim@a @@ -1263,7 +1367,7 @@ {\romannumeral-`\q\skv@tsvnormalize.#1 \normal@nil}% } \skvnewdef*\skv@tsvnormalize#1 #2\normal@nil{% - \skvifblank{#2} + \skvifblankTF{#2} {\expandafter\expandafter\expandafter\space \expandafter\noexpand\@gobble#1} {\skv@tsvnormalize#1#2\normal@nil}% @@ -1337,8 +1441,8 @@ \skv@activeparser#1##1#1~\normal@nil}% }% \def\skv@activeparser##1~##2\normal@nil{% - \skvifblank{##2}{% - \skvifswitch{inkv}{% + \skvifblankTF{##2}{% + \skvifdefswitchTF{inkv}{% \skv@activeequal##1!\normal@nil }{% \skv@spaceparser##1 #1\normal@nil @@ -1348,7 +1452,7 @@ }% }% \def\skv@activeequal##1!##2\normal@nil{% - \skvifblank{##2}{% + \skvifblankTF{##2}{% \skv@spaceparser##1 #1\normal@nil }{% \skv@activeequal##1=##2\normal@nil @@ -1356,15 +1460,15 @@ }% }% \def\skv@spaceparser##1 #1##2\normal@nil{% - \skvifblank{##2}{% + \skvifblankTF{##2}{% \skv@parserspace##1#1 \normal@nil }{% \skv@spaceparser##1#1##2\normal@nil }% }% \def\skv@parserspace##1#1 ##2\normal@nil{% - \skvifblank{##2}{% - \skvifswitch{inkv}{% + \skvifblankTF{##2}{% + \skvifdefswitchTF{inkv}{% \skv@spaceequal##1 =\normal@nil }{% \skv@doubleparser##1#1#1\normal@nil @@ -1374,25 +1478,25 @@ }% }% \def\skv@spaceequal##1 =##2\normal@nil{% - \skvifblank{##2}{% + \skvifblankTF{##2}{% \skv@equalspace##1= \normal@nil }{% \skv@spaceequal##1=##2\normal@nil }% }% \def\skv@equalspace##1= ##2\normal@nil{% - \skvifblank{##2}{% + \skvifblankTF{##2}{% \skv@doubleparser##1#1#1\normal@nil }{% \skv@equalspace##1=##2\normal@nil }% }% \def\skv@doubleparser##1#1#1##2\normal@nil{% - \skvifblank{##2}{% - \skvifswitch{inkv}{% + \skvifblankTF{##2}{% + \skvifdefswitchTF{inkv}{% \skv@doubleequal##1==\normal@nil }{% - \skvifblank{##1}{}{% + \skvifblankTF{##1}{}{% \skv@remleadparser##1\normal@nil }% }% @@ -1401,8 +1505,8 @@ }% }% \def\skv@doubleequal##1==##2\normal@nil{% - \skvifblank{##2}{% - \skvifblank{##1}{}{% + \skvifblankTF{##2}{% + \skvifblankTF{##1}{}{% \skv@remleadparser##1\normal@nil }% }{% @@ -1413,7 +1517,7 @@ \expandafter\space\noexpand##1% }% \def\skv@parserequalerr##1#1=##2\normal@nil{% - \skvifblank{##2}{}{% + \skvifblankTF{##2}{}{% \skv@err{There is '#1=' in your key-value list}\@ehd }% }% @@ -1431,19 +1535,19 @@ \skv@activeslash#1~\normal@nil}% }% \skvnewdef\skv@activeslash#1~#2\normal@nil{% - \skvifblank{#2} + \skvifblankTF{#2} {\skv@spaceslash#1 /\normal@nil} {\skv@activeslash#1/#2\normal@nil}% }% } \skvnewdef\skv@spaceslash#1 /#2\normal@nil{% - \skvifblank{#2} + \skvifblankTF{#2} {\skv@slashspace#1/ \normal@nil} {\skv@spaceslash#1/#2\normal@nil}% } \skvnewdef\skv@slashspace#1/ #2\normal@nil{% - \skvifblank{#2} - {\skvifblank{#1}{}{\expandafter\space\noexpand#1}} + \skvifblankTF{#2} + {\skvifblankTF{#1}{}{\expandafter\space\noexpand#1}} {\skv@slashspace#1/#2\normal@nil}% } @@ -1468,17 +1572,17 @@ \skv@mac@spaceparser##1 #1\normal@nil}% }% \long\def\skv@mac@spaceparser##1 #1##2\normal@nil{% - \skvifblank{##2} + \skvifblankTF{##2} {\skv@mac@parserspace##1#1 \normal@nil} {\skv@mac@spaceparser##1#1##2\normal@nil}% }% \long\def\skv@mac@parserspace##1#1 ##2\normal@nil{% - \skvifblank{##2} + \skvifblankTF{##2} {\skv@mac@doubleparser##1#1#1\normal@nil} {\skv@mac@parserspace##1#1##2\normal@nil}% }% \long\def\skv@mac@doubleparser##1#1#1##2\normal@nil{% - \skvifblank{##2}{ ##1} + \skvifblankTF{##2}{ ##1} {\skv@mac@doubleparser##1#1##2\normal@nil}% }% } @@ -1488,7 +1592,7 @@ \begingroup \def\skv@prova##1{\skvremovescape{##1}@skv@\romannumeral#3}% \def\do##1{\let\noexpand##1\skvnoexpandcs{\skv@prova{##1}}}% - \skvifcsdef{\skvremovescape{#1}@skv@stack}{}{% + \skvifcsdefTF{\skvremovescape{#1}@skv@stack}{}{% \skvcsdef{\skvremovescape{#1}@skv@stack}{}% }% \skvcsxdef{\skvremovescape{#1}@skv@stack}{% @@ -1501,7 +1605,7 @@ \skvrobustdef*\skvpopfunctions#1#2{% \begingroup \edef\skv@elt{\skvnoexpandcs{\skvremovescape{#1}@skv@stack}}% - \expandafter\skvifdef\skv@elt{% + \expandafter\skvifdefTF\skv@elt{% \expandafter\ifx\skv@elt\@empty \skv@err{Stack of '\noexpand#1' is empty}\@ehd \fi @@ -1528,7 +1632,7 @@ \def\skv@loop{% \advance\@tempcnta\@ne % Don't use \ifnum here, because #2 may contain booleans. - \skvifnum\@tempcnta<\numexpr#3+1\relax{% + \skvifnumTF\@tempcnta<\numexpr#3+1\relax{% \edef#1{\skvexpandonce#1.\romannumeral\@tempcnta.{#2}}% \skv@loop }{}% @@ -1572,7 +1676,7 @@ \skvcsvnormalize\skv@prova \def\do##1,{% \ifx\do##1\else - \skvifcsdef{if#1##1}{% + \skvifcsdefTF{if#1##1}{% \skv@err{Boolean '\skvnoexpandcs{if#1##1}' already exists}\@ehd }{% \toks@\expandafter{\the\expandafter\toks@ @@ -1588,12 +1692,12 @@ % Some checks are done in that section. \skvnewbools[skv@]{% - inset,st,cl,pl,kf,inpox,prepo,tracingkeys,swa,swb,% + inset,st,cl,pl,kf,inpox,prepo,tracingkeys,swa,swb,verbose,% intry,insa,success,inoptionsec,inopt,handlerswa,handlerswb% } -\skvnewbools{indirkeys} -\skvnewbools[skv]{indef,novalue,valuebraced} +%\skvnewbools{indirkeys} +\skvnewbools[skv]{indef,indirkeys,novalue,valuebraced} \skvnewbools[dirkeys@]{saveunknownkeys} \skvrobustdef*\skvnewcounts{\skv@testopt\skv@newcounts{}} @@ -1604,7 +1708,7 @@ \skvcsvnormalize\skv@prova \def\do##1,{% \ifx\do##1\else - \skvifcsdef{#1##1}{% + \skvifcsdefTF{#1##1}{% \skv@err{Counter '\skvnoexpandcs{#1##1}' already exists}\@ehd }{% \toks@\expandafter{\the\expandafter\toks@ @@ -1626,7 +1730,7 @@ \skvcsvnormalize\skv@prova \def\do##1,{% \ifx\do##1\else - \skvifcsdef{#1##1}{% + \skvifcsdefTF{#1##1}{% \skv@err{Number '\skvnoexpandcs{#1##1}' already exists}\@ehd }{% \toks@\expandafter{\the\expandafter\toks@ @@ -1655,16 +1759,16 @@ % 3. Package and class options can't be passed via quick keys. % 4. When defining keys, the syntax of <list> is: % -% {<key1,key2,etc>}/{<default>}/{<callback>}/{<choice list>}/{<arg>} +% {<keya-1,...,keya-n>}/{<default>}/{<callback>}/{<choice list>}/{<arg>} % ;...; -% {<key-n>}/{<default>}/{<callback>}/{<choice list>}/{<arg>} +% {<keyb-1,...,keyb-n>}/{<default>}/{<callback>}/{<choice list>}/{<arg>} % % Here, keys key1 and key2 will have the same default value, callback, % choice list and argument pattern. % -% 5. The special key '.exec' will simply execute the code <default>, -% without defining anything. -% 6. Use .na to indicate a missing item that isn't blank. +% 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. % % Example: % \quickkeys.define{fam}[mp@]{% @@ -1673,36 +1777,73 @@ % keyc,keyd/aaa+bbb/\def\x##1{#1*##1*#2}/.na/#1+#2; % } % -\skvnewdef*\skv@ifrejorempty#1{% - \skvifstrcmp{#1}{^skv^}{% +\skvnewdef*\skv@ifstrrejorempty#1{% + \skvifstrcmpTF{#1}{^skv^}{% \@firstoftwo }{% - \skvifblank{#1}{% + \skvifblankTF{#1}{% \@firstoftwo }{% \@secondoftwo }% }% } -\skvnewdef*\skv@ifrejorna#1{% - \skvifstrcmp{#1}{^skv^}{% +\skvnewdef*\skv@ifstrrejordotna#1{% + \skvifstrcmpTF{#1}{^skv^}{% \@firstoftwo }{% - \skvifstrcmp{#1}{.na}{% + \skvifstrcmpTF{#1}{.na}{% \@firstoftwo }{% \@secondoftwo }% }% } -\skvnewdef*\skv@ifrejornaorempty#1{% - \skvifstrcmp{#1}{^skv^}{% +\skvnewdef*\skv@ifstrnut#1{% + \skvifstrcmpTF{#1}{^skv^}{% \@firstoftwo }{% - \skvifstrcmp{#1}{.na}{% + \skvifstrcmpTF{#1}{.na}{% \@firstoftwo }{% - \skvifblank{#1}{% + \skvifblankTF{#1}{% + \@firstoftwo + }{% + \@secondoftwo + }% + }% + }% +} +\skvnewdef*\skv@ifcmdrejorempty#1{% + \skvifxTF#1\skv@rej{% + \@firstoftwo + }{% + \skvifemptyTF#1{% + \@firstoftwo + }{% + \@secondoftwo + }% + }% +} +\skvnewdef*\skv@ifcmdrejordotna#1{% + \skvifxTF#1\skv@rej{% + \@firstoftwo + }{% + \skvifxTF#1\skv@dotna{% + \@firstoftwo + }{% + \@secondoftwo + }% + }% +} +\skvnewdef*\skv@ifcmdnut#1{% + \skvifxTF#1\skv@rej{% + \@firstoftwo + }{% + \skvifxTF#1\skv@dotna{% + \@firstoftwo + }{% + \skvifemptyTF#1{% \@firstoftwo }{% \@secondoftwo @@ -1713,11 +1854,11 @@ \skvrobustdef*\quickkeys#1#{% \edef\skv@tempa{\skvtrimspace{#1}}% - \skvxifstrcmp{\skvexpandonce\skv@tempa}{.define}{% + \skvxifstrcmpTF{\skvexpandonce\skv@tempa}{.define}{% \begingroup\endlinechar\m@ne \skv@defquickkeys }{% - \skvxifstrcmp{\skvexpandonce\skv@tempa}{.set}{% + \skvxifstrcmpTF{\skvexpandonce\skv@tempa}{.set}{% \skv@setquickkeys }{% \skv@err{Unknown task for \string\quickkeys}\@ehd @@ -1729,26 +1870,26 @@ \endgroup \edef\skv@tempa{\skvkeepdoubleslashnormalize{#3}}% \def\skv@defquickkeys@b##1/##2/##3/##4/##5/##6/##7/##8/##9\skv@nil{% - \skvifin{,##1,}{,.exec,.exec code,}{% + \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@ifrejorna{##2}{}{% + \skv@ifstrrejordotna{##2}{}{% \skvcsedef{#1/\skv@tempa/qkeys.def}{\unexpanded{##2}}% }% \skvcsedef{#1/\skv@tempa/qkeys.cbk}{% % ##3 may be empty: - \skv@ifrejorna{##3}{}{\unexpanded{##3}}% + \skv@ifstrrejordotna{##3}{}{\unexpanded{##3}}% }% - \skv@ifrejornaorempty{##4}{}{% + \skv@ifstrnut{##4}{}{% \skvcsedef{#1/\skv@tempa/qkeys.chc}{\unexpanded{##4}}% }% - \skv@ifrejornaorempty{##5}{}{% + \skv@ifstrnut{##5}{}{% \skvcsedef{#1/\skv@tempa/qkeys.arg}{\unexpanded{##5}}% }% - \skvifblank{#2}{}{% + \skvifblankTF{#2}{}{% \skvcsedef{#1/\skv@tempa/qkeys.hp}{\unexpanded{#2}}% }% }% @@ -1772,11 +1913,11 @@ \edef\skv@tempa{\unexpanded{#3}}% \skvkvnormalize\skv@tempa \def\skv@setqkeys##1##2{% - \skvifcsdef{#1/##1/qkeys.cbk}{}{% + \skvifcsdefTF{#1/##1/qkeys.cbk}{}{% \skv@err{Key '#1/##1' is not defined}\@ehd }% - \skvifstrcmp{##2}\skv@novalue{% - \skvifcsdef{#1/##1/qkeys.def}{% + \skvifstrcmpTF{##2}\skv@novalue{% + \skvifcsdefTF{#1/##1/qkeys.def}{% \skvcsletcs{#1/##1/qkeys.val}{#1/##1/qkeys.def}% }{% \skv@err{No user value and no default @@ -1785,20 +1926,20 @@ }{% \skvcsedef{#1/##1/qkeys.val}{\unexpanded{##2}}% }% - \skvifcsdef{#1/##1/qkeys.chc}{% + \skvifcsdefTF{#1/##1/qkeys.chc}{% \skvletcs\reserved@a{#1/##1/qkeys.chc}% \edef\reserved@b{\skvexpandcsonce{#1/##1/qkeys.val}}% - \skvxifin{,\skvoxdetok\reserved@b,}{,\skvoxdetok\reserved@a,}{}{% + \skvxifinTF{,\skvoxdetok\reserved@b,}{,\skvoxdetok\reserved@a,}{}{% \skv@err{Value '\detokenize{##2}' for key '##1' \MessageBreak is not in prescribed list \MessageBreak '\skvoxdetok\reserved@a'}\@ehd }% }{}% - \skvifcsdef{#1/##1/qkeys.hp}{% + \skvifcsdefTF{#1/##1/qkeys.hp}{% \skvletcs\reserved@a{#1/##1/qkeys.hp}% \skvcsletcs{\reserved@a##1}{#1/##1/qkeys.val}% }{}% - \skvifcsdef{#1/##1/qkeys.arg}{% + \skvifcsdefTF{#1/##1/qkeys.arg}{% \skvletcs\reserved@a{#1/##1/qkeys.arg}% }{% \let\reserved@a\skv@simplearg @@ -1811,7 +1952,7 @@ \reserved@a\csname#1/##1/qkeys.val\endcsname\quickkeyseov }% \def\skv@setquickkeys@c##1=##2=##3\skv@nil{% - \skvxifin{,\detokenize{##1},}{,\skvoxdetok\skv@qkeysna,}{}{% + \skvxifinTF{,\detokenize{##1},}{,\skvoxdetok\skv@qkeysna,}{}{% \skv@setqkeys{##1}{##2}% }% }% @@ -1841,7 +1982,7 @@ % % Example: % -% \skvifcase\skvifstrcmp{c} +% \skvifcase\skvifstrcmpTF{c} % {a}{do a} % {b}{do b} % {c}{do c} @@ -1861,16 +2002,16 @@ % % Example: % -% \skvifexpr{% -% not ( expr { \skvifdef\xa } and expr { \skvifempty\xa } ) -% or ( expr { \skvifbool{@tempswa} } or expr { \skvifx\xa\xb } ) +% \skvifexprTF{% +% not ( expr { \skvifdefTF\xa } and expr { \skvifemptyTF\xa } ) +% or ( expr { \skvifboolTF{@tempswa} } or expr { \skvifxTF\xa\xb } ) % }{% % \def\x{T} % }{% % \def\x{F} % } \skvnewnumbers[skv@]{exprcnt} -\skvrobustdef*\skvifexpr#1{% +\skvrobustdef*\skvifexprTF#1{% \begingroup \def\skv@expr@neg{01}% \skvsetno\skv@exprcnt\skvz@ @@ -1901,45 +2042,45 @@ } \skvrobustdef\skv@expr@bgroup#1(#2\skv@expr@nil{% \skv@expr@egroup#1)\skv@expr@nil - \skvifblank{#2}{}{% + \skvifblankTF{#2}{}{% \skv@expr@beg \skv@expr@bgroup#2\skv@expr@nil }% } \skvrobustdef\skv@expr@egroup#1)#2\skv@expr@nil{% \skv@expr@and#1and\skv@expr@nil - \skvifblank{#2}{}{% + \skvifblankTF{#2}{}{% \skv@expr@end \skv@expr@egroup#2\skv@expr@nil }% } \skvrobustdef\skv@expr@and#1and#2\skv@expr@nil{% \skv@expr@or#1or\skv@expr@nil - \skvifblank{#2}{}{% + \skvifblankTF{#2}{}{% \skv@exprcnt\ifnum\skv@exprcnt<\skvz@\m@ne\else\skvz@\fi \skv@expr@and#2\skv@expr@nil }% } \skvrobustdef\skv@expr@or#1or#2\skv@expr@nil{% \skv@expr@not#1not\skv@expr@nil - \skvifblank{#2}{}{% + \skvifblankTF{#2}{}{% \skv@exprcnt\ifnum\skv@exprcnt<\skvz@\skvz@\else\@ne\fi \skv@expr@or#2\skv@expr@nil }% } \skvrobustdef\skv@expr@not#1not#2\skv@expr@nil{% \skv@expr@do#1expr\skv@expr@nil - \skvifblank{#2}{}{% + \skvifblankTF{#2}{}{% \def\skv@expr@neg{00}% \skv@expr@not#2\skv@expr@nil }% } \skvrobustdef\skv@expr@do#1expr#2\skv@expr@nil{% - \skvifblank{#1}{}{% - \skv@err{Invalid \noexpand\skvifexpr test expression} + \skvifblankTF{#1}{}{% + \skv@err{Invalid \noexpand\skvifexprTF test expression} {The handicapped test part is: '\detokenize{#1}'}% }% - \skvifblank{#2}{}{\skv@expr@do@a#2\skv@expr@nil}% + \skvifblankTF{#2}{}{\skv@expr@do@a#2\skv@expr@nil}% } \skvrobustdef\skv@expr@do@a#1#2\skv@expr@nil{% \ignorespaces#1\skv@expr@true\skv@expr@false @@ -1947,7 +2088,7 @@ } \skvnewdef\skvwhileexpr#1\do#2{% - \skvifcond{#1}\fi{#2\skvwhileexpr{#1}\do{#2}}{}% + \skvifcondTF{#1}\fi{#2\skvwhileexpr{#1}\do{#2}}{}% } \skvbuildmacrostack\skv@keystate{% @@ -1958,25 +2099,31 @@ \do\ifskv@inpox\do\ifskv@prepo }\skv@stackdepthlimit -\skvbuildmacrostack\dirkeys@state{% +\skvbuildmacrostack\skv@dirkeys@state{% \do\dirkeys@prefixlist\do\dirkeys@familylist\do\dirkeys@holderprefixtoks \do\dirkeys@unknownkeysmacro\do\ifdirkeys@saveunknownkeys - \do\ifindirkeys + \do\ifskvindirkeys\do\ifskvdfk@initialize\do\ifskvdfk@saveinitialvalues }\skv@stackdepthlimit -\skvrobustdef*\skvappendtomacro{\skv@testst{\skv@appendtomacro{app}{e}}} -\skvrobustdef*\skvgappendtomacro{\skv@testst{\skv@appendtomacro{app}{x}}} -\skvrobustdef*\skvprependtomacro{\skv@testst{\skv@appendtomacro{pre}{e}}} -\skvrobustdef*\skvgprependtomacro{\skv@testst{\skv@appendtomacro{pre}{x}}} +\skvrobustdef\skvappto#1#2{% + \edef#1{\skvexpandonce{#1}\unexpanded{#2}}% +} +\skvrobustdef\skvgappto#1#2{% + \xdef#1{\skvexpandonce{#1}\unexpanded{#2}}% +} +\skvrobustdef\skvappendtomacro{\skv@testst{\skv@appendtomacro{app}{e}}} +\skvrobustdef\skvgappendtomacro{\skv@testst{\skv@appendtomacro{app}{x}}} +\skvrobustdef\skvprependtomacro{\skv@testst{\skv@appendtomacro{pre}{e}}} +\skvrobustdef\skvgprependtomacro{\skv@testst{\skv@appendtomacro{pre}{x}}} \skvrobustdef\skv@appendtomacro#1#2#3#4{% - \skvifescaped{#3}{% + \skvifescapedTF{#3}{% \@nameuse{#2def}#3{% - \skvifstrcmp{#1}{app}{% - \skvifdef#3{\skvexpandonce#3}{}% - \skvifdefbool{skv@tempst}\skvexpandonce\unexpanded{#4}% + \skvifstrcmpTF{#1}{app}{% + \skvifdefTF#3{\skvexpandonce#3}{}% + \skvifdefboolTF{skv@tempst}\skvexpandonce\unexpanded{#4}% }{% - \skvifdefbool{skv@tempst}\skvexpandonce\unexpanded{#4}% - \skvifdef#3{\skvexpandonce#3}{}% + \skvifdefboolTF{skv@tempst}\skvexpandonce\unexpanded{#4}% + \skvifdefTF#3{\skvexpandonce#3}{}% }% }% }{% @@ -1987,7 +2134,7 @@ % \skvaddlist{<parser>}{<listitem>} % This is usually called under \edef. \skvnewdef*\skvaddlist#1#2{% - \skvifempty#2{}{\skvexpandonce#2\unexpanded{#1}}% + \skvifemptyTF#2{}{\skvexpandonce#2\unexpanded{#1}}% } % \skvxaddtolist{<parser>}{<listcmd>}{<newitem>} \skvrobustdef\skvxaddtolist#1#2#3{% @@ -1998,18 +2145,18 @@ \skvrobustdef*\skvgaddtolist{\skv@teststopt{\skv@addtolist{\global}},} \skvrobustdef\skv@addtolist#1[#2]#3#4{% #1\edef#3{% - \skvifdef#3{% - \skvifempty#3{}{\skvexpandonce#3#2}% + \skvifdefTF#3{% + \skvifemptyTF#3{}{\skvexpandonce#3#2}% }{}% - \skvifdefbool{skv@tempst}\skvexpandonce\unexpanded{#4}% + \skvifdefboolTF{skv@tempst}\skvexpandonce\unexpanded{#4}% }% } % \skv@declarefilter{<filter.type>} \skvrobustdef*\skv@declarefilter#1{% \edef\skv@filter##1##2{% - \skvifblank{#1}{\let##2=##1}{% - \skvifx#1\relax{\let##2=##1}{% - \skvifstrcmp{#1}\nofilter{\let##2=##1}{% + \skvifblankTF{#1}{\let##2=##1}{% + \skvifxTF#1\relax{\let##2=##1}{% + \skvifstrcmpTF{#1}\nofilter{\let##2=##1}{% \unexpanded{#1}{##1}{##2}% }% }% @@ -2025,7 +2172,7 @@ \skvrobustdef*\skv@filtermergelist#1#2#3{% \begingroup \skv@declarefilter{#3}% - \skvifdef#1{\skvkvnormalize#1}{\def#1{}}% + \skvifdefTF#1{\skvkvnormalize#1}{\def#1{}}% \edef\skv@merga{\unexpanded{#2}}% \skvkvnormalize\skv@merga \skvcommaloop*\skv@merga\skv@merga{% @@ -2054,11 +2201,11 @@ \skvrobustdef*\skvmergelist{\skv@testcl\skv@mergelist} \skvrobustdef*\skv@mergelist#1#2{% \begingroup - \skvifdef#1{\skvkvnormalize#1}{\def#1{}}% + \skvifdefTF#1{\skvkvnormalize#1}{\def#1{}}% \edef\skv@tempa{\unexpanded{#2}}% \skvkvnormalize\skv@tempa \skvcommaloop*\skv@tempa\skv@tempa{% - \skvxifin{,\skvoxdetok\skv@tempa,}{,\skvoxdetok#1,}{}{% + \skvxifinTF{,\skvoxdetok\skv@tempa,}{,\skvoxdetok#1,}{}{% \edef#1{\skvaddlist,#1\skvexpandonce\skv@tempa}% }% }% @@ -2072,12 +2219,14 @@ % than \skvfilterremoveelements. % \if@tempswa can be used to test if, at the end, anything was % removed from #1. -\skvrobustdef*\skvfilterremoveelements{\skv@testcl\skv@filterremoveelements} +\skvrobustdef*\skvfilterremoveelements{% + \skv@testcl\skv@filterremoveelements +} \skvrobustdef*\skv@filterremoveelements#1#2#3{% \begingroup \let\skv@origlist#1% \skv@declarefilter{#3}% - \skvifdef#1{\skvkvnormalize#1}{\def#1{}}% + \skvifdefTF#1{\skvkvnormalize#1}{\def#1{}}% \skvcommaparse{#2}\skv@rema\skv@rema{% \skv@filter\skv@rema\skv@remb \let\skv@remc#1\let#1\@empty @@ -2107,12 +2256,12 @@ \skvrobustdef\skv@removeelements#1#2{% \begingroup \let\skv@origlist#1% - \skvifdef#1{}{\def#1{}}% + \skvifdefTF#1{}{\def#1{}}% \edef\skv@rema{\unexpanded{#2}}% \skvcsvnormalize\skv@rema \let\skv@remb#1\let#1\@empty \skvcommaparse*\skv@remb\skv@tempa{% - \skvxifin{,\skvoxdetok\skv@tempa,}{,\skvoxdetok\skv@rema,}{}{% + \skvxifinTF{,\skvoxdetok\skv@tempa,}{,\skvoxdetok\skv@rema,}{}{% \edef#1{\skvaddlist,#1\skvexpandonce\skv@tempa}% }% }% @@ -2138,11 +2287,13 @@ % 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} +\skvrobustdef*\skvfilterreplaceelements{% + \skv@testcl\skv@filterreplaceelements +} \skvrobustdef*\skv@filterreplaceelements#1#2#3{% \begingroup \skv@declarefilter{#3}% - \skvifdef#1{\skvkvnormalize#1}{\def#1{}}% + \skvifdefTF#1{\skvkvnormalize#1}{\def#1{}}% \def\do##1##2\skv@nil{% \ifx#3\skv@getkeyname \def\@do####1=####2=####3\skv@nil####4{% @@ -2189,24 +2340,30 @@ \skv@prefix\ifx\skvcurrentfamily\@empty\else\skvcurrentfamily/\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}}% } \skvrobustdef*\skv@t@stopta#1{\skvifplus{\skv@pltrue#1}{\skv@plfalse#1}} -\skvrobustdef*\skv@testoptb#1{\skv@testopt{\skv@t@stoptb{#1}}{KV}} +\skvrobustdef*\skv@testoptb#1{% + \skv@testopt{\skv@t@stoptb{#1}}\skv@defaultpref +} \skvrobustdef*\skv@t@stoptb#1[#2]#3{% \skv@makeprefix{#2}\skv@makeheader{#3}#1% } -\skvrobustdef*\skv@testoptc#1{\skv@testopt{\skv@t@stoptc{#1}}{KV}} +\skvrobustdef*\skv@testoptc#1{% + \skv@testopt{\skv@t@stoptc{#1}}\skv@defaultpref +} \skvrobustdef*\skv@t@stoptc#1[#2]#3{% - \skvxifin{,}{\detokenize{#2}}{% + \skvxifinTF{,}{\detokenize{#2}}{% \skv@err{Only one prefix is allowed here, \MessageBreak but you gave '#2'}\@ehd }{% \skv@makeprefix{#2}% \edef\skv@fams{#3}% - \skvxifin{,}{\detokenize{#3}}{% + \skvxifinTF{,}{\detokenize{#3}}{% \skvcsvnormalize\skv@fams }{% \skvdespacecontent\skv@fams @@ -2214,6 +2371,7 @@ \skv@testopt#1{}% }% } +% \skv@testoptd{<cmd>}{<pre-mp>} \skvrobustdef*\skv@testoptd#1#2{% \skv@testoptb{% \edef\skv@provb{#2\skv@header}% @@ -2221,6 +2379,7 @@ \expandafter\skv@prova\expandafter{\skv@provb}% }% } +% \skv@t@stoptd{<cmd>}[<mp>]{<key>} \skvrobustdef*\skv@t@stoptd#1[#2]#3{% \skvifnextchar[{\skv@sttrue#1{#2}{#3}}{\skv@stfalse#1{#2}{#3}[]}% } @@ -2252,15 +2411,15 @@ } \skvrobustdef*\skv@definedefault#1#2{% \ifskv@inoptionsec\else - \skvxifin{,\skvcurrentprefix,}{,skv,SKV,}{% - \skvxifin{,\skvcurrentfamily,}{,skeyval,}{% + \skvxifinTF{,\skvcurrentprefix,}{,skv,SKV,}{% + \skvxifinTF{,\skvcurrentfamily,}{,skeyval,}{% \skv@err{Prefix/family '\skvcurrentprefix/\skvcurrentfamily' are reserved}\@ehd }{}% }{}% \fi \ifskv@tracingkeys - \skvxifin{,#1,}{,\skv@badkeynames,}{% + \skvxifinTF{,#1,}{,\skv@badkeynames,}{% \skv@err{Key name '#1' not allowed}\@ehd }{}% \fi @@ -2285,18 +2444,18 @@ % create 'needini' lists of families. \skvrobustdef*\skv@recordkey#1#2{% \begingroup - \skvifcsundef{\skv@header.@needini}{% + \skvifcsdefFT{\skv@header.@needini}{% \endgroup\skv@swafalse }{% \skv@swatrue - \skvxifin{,#1,}{,\skvexpandcsonce{\skv@header.@needini},}{% + \skvxifinTF{,#1,}{,\skvexpandcsonce{\skv@header.@needini},}{% \edef\skv@tempa{\skvtrimspace{#2}}% \edef\skv@tempa{% - #1=\skvoifstrcmp{\skv@tempa}{true}{false}{\skvexpandonce\skv@tempa}% + #1=\skvoifstrcmpTF{\skv@tempa}{true}{false}{\skvexpandonce\skv@tempa}% }% \skvletcs\skv@tempb{\skv@header.@inikv}% - \skvifdef\skv@tempb{% - \skvxifin{,\skvoxdetok\skv@tempa,}{,\skvoxdetok\skv@tempb,}{}{% + \skvifdefTF\skv@tempb{% + \skvxifinTF{,\skvoxdetok\skv@tempa,}{,\skvoxdetok\skv@tempb,}{}{% \skvcsedef{\skv@header.@inikv}{% \skvaddlist,\skv@tempb\skvexpandonce\skv@tempa }% @@ -2326,7 +2485,7 @@ \skvrobustdef*\skv@strippointers#1#2{% \begingroup \edef#2{% - \skvifstrcmp{#1}{\skvcurrentkey} + \skvifstrcmpTF{#1}{\skvcurrentkey} {\skvcurrentkey}{\skvtrimspace{#1}}% }% \def\skv@prova{\expandafter\skv@findpointer\expandafter}% @@ -2336,48 +2495,41 @@ % 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{% - \def\do{\skvcsdef{\skv@header#2.@ndv}{00}}% + \skv@add{\skvcsdef{\skv@header#2.@ndv}{00}}% }{% - \skv@prova{#2}{.require value}#2{% - \def\do{\skvcsdef{\skv@header#2.@ndv}{00}}% + \skv@prova{#2}{.forbid value}#2{% + \skv@add{\skvcsdef{\skv@header#2.@fbv}{00}}% }{% - \skv@prova{#2}{.value required}#2{% - \def\do{\skvcsdef{\skv@header#2.@ndv}{00}}% + \skv@prova{#2}{.expanded}#2{% + \edef#2{#2}% }{% - \skv@prova{#2}{.forbid value}#2{% - \def\do{\skvcsdef{\skv@header#2.@fbv}{00}}% + \skv@prova{#2}{.expand once}#2{% + \edef#2{\skvexpandtwice{#2}}% }{% - \skv@prova{#2}{.value forbidden}#2{% - \def\do{\skvcsdef{\skv@header#2.@fbv}{00}}% - }{% - \skv@prova{#2}{.expanded}#2{% - \edef#2{#2}% - }{% - \skv@prova{#2}{.expand once}#2{% - \edef#2{\skvexpandtwice{#2}}% - }{% - \skv@prova{#2}{.expand twice}#2{% - \edef#2{\skvexpandthrice{#2}}% - }{}% - }% - }% - }% + \skv@prova{#2}{.expand twice}#2{% + \edef#2{\skvexpandthrice{#2}}% + }{}% }% }% }% }% - \skvexpanded{\endgroup - \skvcmdexit{#2}\do - }% + \skvexpanded{\endgroup\skvcmdexit#2\do}% } \skvrobustdef*\skv@findpointer#1#2#3{% \begingroup \def\skv@prova##1#2##2##3\pointer@nil{% \endgroup - \skvifstrcmp{##2}{\skv@nil}{% + \skvifstrcmpTF{##2}{\skv@nil}{% \@secondoftwo }{% + \skviflacus##1\then\else + \skv@err{Nothing should come before the + \MessageBreak pointer '#2' on key '##2'}\@ehd + \fi \edef#3{\skvtrimspace{##2}}% \@firstoftwo }% @@ -2404,7 +2556,7 @@ \ifx#2\@empty \edef#2{\unexpanded{#1}}% \else - \skvifstreq{#2}\with{\skvcurrentkey}\then + \skvifstreq{#2}{\skvcurrentkey}\then \in@true % The number of arguments of the pseudo key is determined by the % number of closed parentheses: @@ -2443,7 +2595,7 @@ \begingroup \let\skvcurrentvalue\@empty \let\skv@tempa\@empty - \skvifbraced{#1}{% + \skvifbracedTF{#1}{% \skv@r@placepointers{#1}.use value\skv@nil }{% \skv@r@placepointers#1.use value\skv@nil @@ -2459,20 +2611,20 @@ % \skvrobustdef*\skv@r@placepointers#1.use value#2{% \edef\skv@prova{\unexpanded{#2}}% - \skvifx\skv@prova\skv@nnil{% + \skvifxTF\skv@prova\skv@nnil{% \edef\skvcurrentvalue{\unexpanded{#1}}% }{% - \skvifcsundef{\skv@header#2.@value}{% + \skvifcsdefFT{\skv@header#2.@value}{% \skv@err{No value recorded for key '#2'; ignored}\@ehd \skv@r@placepointers }{% - \skvxifin{,\detokenize{#2},}{,\skvoxdetok\skv@tempa,}{% + \skvxifinTF{,\detokenize{#2},}{,\skvoxdetok\skv@tempa,}{% \skv@err{Back linking of pointers; \MessageBreak pointer replacement canceled}\@ehd }{% \edef\skv@tempa{\skvaddlist,\skv@tempa\unexpanded{#2}}% \edef\skv@prova{\skvexpandcsonce{\skv@header#2.@value}}% - \skvexpandbracenext\skvifbraced\skv@prova{% + \skvexpandbracenext\skvifbracedTF\skv@prova{% \skvexpandbracenext{\skv@r@placepointers#1}\skv@prova }{% \skvexpandnext{\skv@r@placepointers#1}\skv@prova @@ -2508,7 +2660,7 @@ % % which will be used at setkeys to define and execute the key's callback. % -\skvrobustdef*\skvassignargs{\skv@testopt\skv@assignargs{KV}} +\skvrobustdef*\skvassignargs{\skv@testopt\skv@assignargs\skv@defaultpref} \skvrobustdef*\skv@assignargs[#1]#2{% \begingroup \skv@testopt{\skv@assignargs@a{#1}{#2}}{^skv^}% @@ -2516,7 +2668,7 @@ \skvrobustdef*\skv@assignargs@a#1#2[#3]#4#5{% \edef\skv@tempc{\skvtrimspace{#5}}% \def\skv@tempd{}% - \skvifstrcmp{#3}{^skv^}{% + \skvifstrcmpTF{#3}{^skv^}{% \def\skvexpander{x0}% }{% \skv@checkexpander{#3}% @@ -2539,7 +2691,7 @@ \skvexpanded{\endgroup\skv@tempd}% } \skvrobustdef*\skv@checkexpander#1{% - \skvxifin{,\expandafter\skvtrimspace\expandafter + \skvxifinTF{,\expandafter\skvtrimspace\expandafter {\detokenize\expandafter{#1}},}{,\detokenize{x0,x1,x2,xx},}{}{% \skv@err{Illegal expansion type '#1'}\@ehd }% @@ -2555,7 +2707,7 @@ \skvexpanded{\skv@testopt{\skv@ordkey@a{\skvcurrentkey}}{^skv^}}% } \skvrobustdef*\skv@ordkey@a#1[#2]#3{% - \skvifstrcmp{#2}{^skv^}{}{\skv@definedefault{#1}{#2}}% + \skvifstrcmpTF{#2}{^skv^}{}{\skv@definedefault{#1}{#2}}% \skvcsedef{\skv@header#1.@cbk}{\unexpanded{#3}}% } \skvrobustdef*\skvordkeys{\skv@testoptb\skv@ordkeys} @@ -2579,7 +2731,7 @@ \skvexpanded{\skv@testopt{\skv@voidkey@a{\skvcurrentkey}}{^skv^}}% } \skvrobustdef*\skv@voidkey@a#1[#2]#3{% - \skvifstrcmp{#2}{^skv^}{}{\skv@definedefault{#1}{#2}}% + \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{% @@ -2625,7 +2777,7 @@ \skvexpanded{\skv@testopt{\skv@pntkey@a{\skvcurrentkey}}{^skv^}}% } \skvrobustdef*\skv@pntkey@a#1[#2]#3{% - \skvifstrcmp{#2}{^skv^}{}{\skv@definedefault{#1}{#2}}% + \skvifstrcmpTF{#2}{^skv^}{}{\skv@definedefault{#1}{#2}}% \skvcsedef{\skv@header#1.@cbk}{\unexpanded{#3}}% } @@ -2634,38 +2786,37 @@ % \skvcmdkey[<pref>]{<fam>}[<mp>]{<key>}[<defa>]{<callback>} % \skvrobustdef*\skvcmdkey{% - \def\skv@zapnr{0}% + \def\skv@zapsw{01}% \skv@testoptd\skv@cmdkey{cmd}% } - % \skvzcmdkey will internally zap the spaces in the key's name, but the % key user will not notice that: he can still use the key's name with % spaces in it. The key's author could then use the zapped name internally % in his code. \skvrobustdef*\skvzcmdkey{% - \def\skv@zapnr{1}% + \def\skv@zapsw{00}% \skv@testoptd\skv@cmdkey{cmd}% } % 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 - \skvifdefbool{skv@st}{\skv@definedefault\skvcurrentkey{#3}}{}% + \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@zapnr\expandafter}\expandafter{\skv@prova}}% + {\expandafter\skv@zapsw\expandafter}\expandafter{\skv@prova}}% \skvcslet{\skv@header\skvcurrentkey.@hp}\skv@prova \skvcsedef{\skv@header\skvcurrentkey.@cbk}{\unexpanded{#4}}% } % \skvcmdkeys[<pref>]{<fam>}[<mp>]{<keys>}[<defa>]{<callback>} \skvrobustdef*\skvcmdkeys{% - \def\skv@zapnr{0}% + \def\skv@zapsw{01}% \skv@testoptd\skv@cmdkeys{cmd}% } \skvrobustdef*\skvzcmdkeys{% - \def\skv@zapnr{1}% + \def\skv@zapsw{00}% \skv@testoptd\skv@cmdkeys{cmd}% } \skvrobustdef*\skv@cmdkeys#1#2[#3]#4{% @@ -2676,63 +2827,202 @@ %% Choice keys: % +% The skeyval package allows holder-macro prefixes {<mp>} for choice keys. +% % \skvchoicekey[<pref>]{<fam>}[<mp>]{<key>}[<bins>]{<choices>} -% [<defa>]{<callback>} +% [<default>]{<callback>} +% \skvchoicekey+[<pref>]{<fam>}[<mp>]{<key>}[<bins>]{<choices>} +% [<default>]{<callback>}{<fallback>} +% \skvchoicekey*[<pref>]{<fam>}[<mp>]{<key>}[<bins>]{<choices>} +% [<default>]{<callback>} +% \skvchoicekey*+[<pref>]{<fam>}[<mp>]{<key>}[<bins>]{<choices>} +% [<default>]{<callback>}{<fallback>} % -% The skeyval package allows holder-macro prefixes for choice keys. +% \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}} +% +% \skv@preparenominations{00.or.01}{<altlist>} +\skvrobustdef*\skv@preparenominations#1#2{% + \begingroup + \def\skv@altlista{}% + \def\skv@altlistb{}% + \def\skv@provc##1.do=##2.do=##3\skv@choice@nil{% + \if#1\lowercase{\fi + \edef\skv@prova{\skvtrimspace{##1}}% + \if#1}\fi + \skvstripouterbraces{2}\skv@prova + \edef\skv@altlista{% + \skvxonce\skv@altlista\ifx\skv@altlista\@empty\else,\fi + \skvxonce\skv@prova + }% + \edef\reserved@a{% + \skvnoexpandcs{\skvoxdetok\skv@prova @skvch}% + {\skvtrimspace{##2}}% + }% + \edef\skv@altlistb{\skvxonce\skv@altlistb\skvxonce\reserved@a}% + }% + \skvcommaparse{#2}\skv@prova{% + \expandafter\skv@provc\skv@prova.do=.do=\skv@choice@nil + }% + \ifx\skv@altlista\@empty + \skv@err{No nominations (state pattern) for choice key}\@ehd + \def\skv@altlistb{}% + \fi + \skvexpanded{\endgroup + \skvcmdexit\skv@altlista\skvcmdexit\skv@altlistb + }% +} +% \skv@executechoice{00.or.01}{<currentvalue>}{<altlist>} +\skvrobustdef*\skv@executechoice#1#2#3{% + \begingroup + \if#1\lowercase{\fi + \edef\skv@prova{\skvtrimspace{#2}}% + \if#1}\fi + \skvstripouterbraces{2}\skv@prova + \edef\do{% + \expandafter\noexpand\csname\detokenize + \expandafter{\skv@prova}@skvch\endcsname + }% + % Hide #3 in a macro to avoid confusing any parameter + % characters in #3 with the parameters of \skv@prova: + \edef\skv@provb{\unexpanded{#3}}% + \edef\skv@prova{\def\noexpand\skv@prova####1\skvxonce\do####2####3}% + \skv@prova\skv@choice@nil{% + \toks@{##2}% + \edef\skv@prova{\unexpanded{##2}}% + \ifx\skv@prova\skv@nnil + \skv@err{No state pattern match found for key + \MessageBreak '\skvcurrentkey'}\@ehd + \toks@{}% + \fi + }% + \expandafter\expandafter\expandafter\skv@prova\expandafter + \skv@provb\do{\skv@nil}\skv@choice@nil + \expandafter\endgroup\the\toks@ +} \skvrobustdef*\skvchoicekey{% \skv@testopta{\skv@testoptb {\skv@testopt\skv@choicekey@a{choice\skv@header}}}% } +\skvnewlet\skvchoicekeys\skvchoicekey \skvrobustdef*\skv@choicekey@a[#1]#2{% - \skv@strippointers{#2}\skvcurrentkey - \skvcsedef{\skv@header\skvcurrentkey.@hp}{% - \skvtrimspace{#1}\skvcurrentkey + \skvxifinTF{\skv@hashchar}{\detokenize{#2}}{% + \skv@err{Hash character '\skv@hashchar' not allowed + \MessageBreak in key name}\@ehd + }{% + \edef\skv@currlist{\unexpanded{#2}}% + \edef\skv@hp{\skvtrimspace{#1}}% + \skv@testopt\skv@choicekey@b{}% }% - \skv@testopt\skv@choicekey@b{}% } \skvrobustdef*\skv@choicekey@b[#1]#2{% - \def\skv@bins{#1}% - \edef\skv@tempa{\unexpanded{#2}}% - \skvcsvnormalize\skv@tempa - \skv@toksa\expandafter{\skv@tempa}% + \edef\skv@bins{\unexpanded{#1}}% + % Check the syntax of bins. This also helps catch wrong use syntax + % of \skvchoicekeys: it's easy to get the syntax of \skvchoicekeys + % wrong. The default value may have been put in place of bins. + \ifx\skv@bins\@empty\else + \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 + }% + }% + \fi + \skvifblankTF{#2}{% + \skv@err{No nominations (state pattern) for + \MessageBreak choice keys '\skv@currlist'}\@ehd + }{% + \skvifboolTF{skv@st}{% + \skv@preparenominations{00}{#2}% + }{% + \skv@preparenominations{01}{#2}% + }% + }% \skvifnextchar[\skv@choicekey@c{\skv@choicekey@c[^skv^]}% } \skvrobustdef*\skv@choicekey@c[#1]{% - \skvifstrcmp{#1}{^skv^}{}{\skv@definedefault\skvcurrentkey{#1}}% - \skvifdefbool{skv@pl}\skv@choicekey@e\skv@choicekey@d + \edef\skv@default{\skvtrimspace{#1}}% + % Choice can't have braced values, since that will make matching + % to state pattern difficult: + \skvstripouterbraces{2}\skv@default + \skvifdefboolTF{skv@pl}\skv@choicekey@e\skv@choicekey@d +} +\skvrobustdef*\skv@choicekey@d#1{% + \skvexpanded{% + \noexpand\skv@choicekey@f{{% + \noexpand\skv@executechoice\ifskv@st{00}\else{01}\fi + {####1}{\skvxonce\skv@altlistb}% + \unexpanded{#1}% + }}% + }% +} +\skvrobustdef*\skv@choicekey@e#1#2{% + \skvexpanded{% + \noexpand\skv@choicekey@f{{% + \noexpand\skv@executechoice\ifskv@st{00}\else{01}\fi + {####1}{\skvxonce\skv@altlistb}% + \unexpanded{#1}% + }{\unexpanded{#2}}}% + }% } -\skvrobustdef*\skv@choicekey@d#1{\skv@choicekey@f{{#1}}} -\skvrobustdef*\skv@choicekey@e#1#2{\skv@choicekey@f{{#1}{#2}}} \skvrobustdef*\skv@choicekey@f#1{% - \edef\skv@tempa##1##2{% + \edef\skv@prova##1##2{% \ifskv@st\noexpand\skv@sttrue\else\noexpand\skv@stfalse\fi \ifskv@pl\noexpand\skv@pltrue\else\noexpand\skv@plfalse\fi - \skv@checkchoice[\skvexpandonce\skv@bins]{##1}{\the\skv@toksa}##2% + \noexpand\skv@checkchoice + \ifx\skv@bins\@empty\else[\skvxonce\skv@bins]\fi + {##1}{\skvxonce\skv@altlista}##2% }% - \skv@toksa\expandafter{\skv@tempa{##1}{#1}}% - \skvcsedef{\skv@header\skvcurrentkey.@cbk}{\the\skv@toksa}% + \skv@toksa\expandafter{\skv@prova{##1}{#1}}% + % Why separate \skv@choicekey@g? It is needed by skeyval-view.sty: + \skv@choicekey@g +} +\skvrobustdef*\skv@choicekey@g{% + \skvcommaparse*\skv@currlist\skv@prova{% + \skvexpbracenext\skv@strippointers\skv@prova\skvcurrentkey + \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}% + }% +} + +\skvrobustdef*\skv@togkey@settog#1#2#3{% + \edef\skv@prova{\skv@zapornot{#1}{#2}}% + \csname skvsettog#3\expandafter\endcsname\expandafter{\skv@prova}% } %% Boolean keys: % % \skvboolkey[<pref>]{<fam>}[<mp>]{<key>}[<defa>]{<callback>} +% \skvboolkey+[<pref>]{<fam>}[<mp>]{<keys>}[<defa>]{<callback>}{<fallback>} % % Boolean keys create a store to receive the key's value and also create % a boolean internally. +% \skvrobustdef*\skvboolkey{% - \def\skv@zapnr{0}% + \def\skv@typetogkey{01}% + \def\skv@zapsw{01}% \skv@t@stopta{\skv@testoptd\skv@boolkey{}}% } -% \skvzcmdkey will internally zap the spaces in the key's name and in +% \skvzboolkey will internally zap the spaces in the key's name and in % the boolean that it creates internally, but the key user will not % notice that: he will still be able to submit the original key's name % with spaces in it. The key's author could then use the zapped key % name and boolean in his code (internally). \skvrobustdef*\skvzboolkey{% - \def\skv@zapnr{1}% + \def\skv@typetogkey{01}% + \def\skv@zapsw{00}% \skv@t@stopta{\skv@testoptd\skv@boolkey{}}% } +% \skv@boolkeys{<mp>}{<key>}[<default>] \skvrobustdef*\skv@boolkey#1#2[#3]{% \skv@strippointers{#2}\skvcurrentkey \skvexpanded{% @@ -2740,21 +3030,38 @@ {\skvcurrentkey}{#1\skvcurrentkey}% }{#3}% } +% \skv@boolkey@a{<key>}{<mp.key>}{<default>}{<callback>} \skvrobustdef*\skv@boolkey@a#1#2#3#4{% \def\skv@tempa{\skv@boolkey@c{#1}{#2}{#3}}% - \expandafter\skv@tempa\expandafter{\expandafter{\expandafter - \csname\expandafter\skv@zapornot\expandafter{\skv@zapnr}{#2}% - \skv@value\endcsname#4}}% + \skvifplaswTF\skv@typetogkey{% + \expandafter\skv@tempa\expandafter{\expandafter{\expandafter + \skv@togkey@settog\expandafter{\skv@zapsw}{#2}\skv@value#4}}% + }{% + \expandafter\skv@tempa\expandafter{\expandafter{\expandafter + \csname\expandafter\skv@zapornot\expandafter{\skv@zapsw}{#2}% + \skv@value\endcsname#4}}% + }% } +% \skv@boolkey@b{<key>}{<mp.key>}{<default>}{<callback>}{<fallback>} \skvrobustdef*\skv@boolkey@b#1#2#3#4#5{% \def\skv@tempa{\skv@boolkey@c{#1}{#2}{#3}}% - \expandafter\skv@tempa\expandafter{\expandafter{\expandafter - \csname\expandafter\skv@zapornot\expandafter{\skv@zapnr}{#2}% - \skv@value\endcsname#4}{#5}}% + \skvifplaswTF\skv@typetogkey{% + \expandafter\skv@tempa\expandafter{\expandafter{\expandafter + \skv@togkey@settog\expandafter{\skv@zapsw}{#2}\skv@value#4}{#5}}% + }{% + \expandafter\skv@tempa\expandafter{\expandafter{\expandafter + \csname\expandafter\skv@zapornot\expandafter{\skv@zapsw}{#2}% + \skv@value\endcsname#4}{#5}}% + }% } +% \skv@boolkey@c{<key>}{<mp.key>}{<default>}{{<callback>}{<fallback>}} \skvrobustdef*\skv@boolkey@c#1#2#3#4{% - \skvcsnewif{\skv@zapornot{\skv@zapnr}{#2}}% - \skvifdefbool{skv@st}{\skv@definedefault{#1}{#3}}{}% + \if\skv@typetogkey + \skvdeftog{\skv@zapornot{\skv@zapsw}{#2}}% + \else + \skvcsnewif{\skv@zapornot{\skv@zapsw}{#2}}% + \fi + \skvifdefboolTF{skv@st}{\skv@definedefault{#1}{#3}}{}% \edef\skv@tempa##1##2{% \noexpand\skv@sttrue \ifskv@pl\noexpand\skv@pltrue\else\noexpand\skv@plfalse\fi @@ -2763,25 +3070,33 @@ \skv@toksa\expandafter{\skv@tempa{##1}{#4}}% \skvcsedef{\skv@header#1.@cbk}{\the\skv@toksa}% } +% % \skvboolkeys[<pref>]{<fam>}[<mp>]{<keys>}[<defa>]{<callback>} +% \skvboolkeys+[<pref>]{<fam>}[<mp>]{<keys>}[<defa>]{<callback>}{<fallback>} +% \skvrobustdef*\skvboolkeys{% - \def\skv@zapnr{0}% + \def\skv@typetogkey{01}% + \def\skv@zapsw{01}% \skv@t@stopta{\skv@testoptd\skv@boolkeys{}}% } \skvrobustdef*\skvzboolkeys{% - \def\skv@zapnr{1}% + \def\skv@typetogkey{01}% + \def\skv@zapsw{00}% \skv@t@stopta{\skv@testoptd\skv@boolkeys{}}% } +% \skv@boolkeys{<mp>}{<keys>}[<default>] \skvrobustdef*\skv@boolkeys#1#2[#3]{% - \skvifdefbool{skv@pl}\skv@boolkeys@b\skv@boolkeys@a{#2}{#1}{#3}% + \skvifdefboolTF{skv@pl}\skv@boolkeys@b\skv@boolkeys@a{#2}{#1}{#3}% } +% \skv@boolkeys@a{<keys>}{<mp>}{<default>}{<callback>} \skvrobustdef*\skv@boolkeys@a#1#2#3#4{\skv@boolkeys@c{#1}{#2}{#3}{#4}{^skv^}} +% \skv@boolkeys@b{<keys>}{<mp>}{<default>}{<callback>}{<fallback>} \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 \skvexpanded{% - \skvifstrcmp{#5}{^skv^}{% + \skvifstrcmpTF{#5}{^skv^}{% \skv@boolkey@a{\skvcurrentkey}% {#2\skvcurrentkey}\unexpanded{{#3}{#4}}% }{% @@ -2791,6 +3106,170 @@ }% }% } +% +% \skvbiboolkeys[<pref>]{<fam>}[<mp>]{<key1,key2>}[<defa>] +% {<callback.for.key1>}{<callback.for.key2>} +% \skvbiboolkeys+[<pref>]{<fam>}[<mp>]{<key1,key2>}[<defa>] +% {<callback.for.key1>}{<callback.for.key2>}{<fallback>} +% +% Example: +% +% \skvbiboolkeys+[KV]{fam}[mp@]{.need value{keya},keyb}[true]{% +% \ifmp@keya\def\xa##1{##1}\fi +% }{% +% \ifmp@keyb\def\xb##1{##1}\fi +% }{% +% \skv@warn{Value '#1' is invalid}% +% } +% +\skvrobustdef*\skvbiboolkeys{% + \def\skv@typetogkey{01}% + \def\skv@zapsw{01}% + \skv@t@stopta{\skv@testoptd\skv@biboolkeys{}}% +} +\skvrobustdef*\skvzbiboolkeys{% + \def\skv@typetogkey{01}% + \def\skv@zapsw{00}% + \skv@t@stopta{\skv@testoptd\skv@biboolkeys{}}% +} +\skvrobustdef*\skv@biboolkeys#1#2[#3]{% + \begingroup + \edef\skv@currlist{\unexpanded{#2}}% + \skvcsvnormalize\skv@currlist + \@tempcnta\skvz@ + \skvcommaloop*\skv@currlist\skv@tempa{% + \advance\@tempcnta\@ne + \ifnum\@tempcnta>\tw@ + \skvbreakloop + \fi + }% + \ifnum\@tempcnta=\tw@\else + \skv@err{Number of bi-keys isn't 2: + \MessageBreak ||\skv@currlist||}\@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>} +\skvrobustdef*\skv@biboolkeys@a#1#2#3#4#5{% + \skv@biboolkeys@c{#1}{#2}{#3}{#4}{#5}{^skv^}% +} +% \skv@bilboolkeys@a{<key1,key2>}{<mp>}{<default>} +% {<callback1>}{<callback2>}{<fallback>} +\skvrobustdef*\skv@biboolkeys@b#1#2#3#4#5#6{% + \skv@biboolkeys@c{#1}{#2}{#3}{#4}{#5}{#6}% +} +\skvrobustdef*\skv@biboolkeys@c#1#2#3#4#5#6{% + % Don't group the following: pointers will be lost outide the group. + % 'bicallerid' is used to indicate that the master key is the one + % that has instantiated the callback of the slave. This avoids + % infinite re-entrance of \skvsetkeys. + \edef\skv@default{\unexpanded{#3}}% + \edef\skv@tempc{\unexpanded{#4}}% + \edef\skv@tempd{\unexpanded{#5}}% + \edef\skv@tempe{\unexpanded{#6}}% + \toks@{}\def\skv@provd{}% + \let\\\noexpand + \def\@do##1##2{% + \skvifcsname\skv@header##1.@##2\then + \edef\skv@provd{% + \skv@provd + \skvcsdef{\skv@header##1.@##2}{% + \csname\skv@header##1.@##2\endcsname + }% + }% + \fi + }% + \def\skv@provc##1##2##3##4{% + \skvsettogtrue{\skv@header bicallerid/##3}% + \skvxonce\@elt + \\\skvifxTF\\\skvcurrentvalue\\\skv@truetoks{% + \\\skviftogTF{\skv@header bicallerid/##4}{}{% + \skvsetkeys[##1]{##2}{##4=false}% + }% + }{% + \\\skviftogTF{\skv@header bicallerid/##4}{}{% + \skvsetkeys[##1]{##2}{##4=true}% + }% + }% + \skvsettogfalse{\skv@header bicallerid/##3}% + }% + % \skv@provb{<KV>}{<fam>}{<primary.key>}{<secondary.key>} + \def\skv@provb##1##2##3##4{% + \@do{##3}{ndv}\@do{##3}{fbv}% + \skvexpanded{% + \toks@{\the\toks@ + \skvdeftog{\skv@header bicallerid/##3}% + \skvifstrcmpTF{#6}{^skv^}{% + \skv@boolkey@a + {##3}{#2##3}{\skvxonce\skv@default}{% + \skv@provc{##1}{##2}{##3}{##4}% + }% + }{% + \skv@boolkey@b + {##3}{#2##3}{\skvxonce\skv@default}{% + \skv@provc{##1}{##2}{##3}{##4}% + }{\skvxonce\skv@tempe}% + }% + }% + }% + }% + \def\skv@prova##1,##2\skv@nil{% + \skv@strippointers{##1}\skv@tempa + \skv@strippointers{##2}\skv@tempb + \skvexpanded{% + \let\\\@elt\\\skv@tempc + \\\skv@provb{\skvcurrentprefix}{\skvcurrentfamily}% + {\skv@tempa}{\skv@tempb}% + \let\\\@elt\\\skv@tempd + \\\skv@provb{\skvcurrentprefix}{\skvcurrentfamily}% + {\skv@tempb}{\skv@tempa}% + }% + }% + \skv@prova#1\skv@nil + \skvexpanded{\endgroup + \skv@provd\the\toks@ + }% +} + +%% Toggle keys: +% +% \skvtogkey[<pref>]{<fam>}[<mp>]{<key>}[<defa>]{<callback>} +% \skvtogkey+[<pref>]{<fam>}[<mp>]{<key>}[<defa>]{<callback>}{<fallback>} +% +\skvrobustdef*\skvtogkey{% + \def\skv@typetogkey{00}% + \def\skv@zapsw{01}% + \skv@t@stopta{\skv@testoptd\skv@boolkey{}}% +} +\skvrobustdef*\skvztogkey{% + \def\skv@typetogkey{00}% + \def\skv@zapsw{00}% + \skv@t@stopta{\skv@testoptd\skv@boolkey{}}% +} +\skvrobustdef*\skvtogkeys{% + \def\skv@typetogkey{00}% + \def\skv@zapsw{01}% + \skv@t@stopta{\skv@testoptd\skv@boolkeys{}}% +} +\skvrobustdef*\skvztogkeys{% + \def\skv@typetogkey{00}% + \def\skv@zapsw{00}% + \skv@t@stopta{\skv@testoptd\skv@boolkeys{}}% +} +\skvrobustdef*\skvbitogkeys{% + \def\skv@typetogkey{00}% + \def\skv@zapsw{01}% + \skv@t@stopta{\skv@testoptd\skv@biboolkeys{}}% +} +\skvrobustdef*\skvzbitogkeys{% + \def\skv@typetogkey{00}% + \def\skv@zapsw{00}% + \skv@t@stopta{\skv@testoptd\skv@biboolkeys{}}% +} % Style keys % @@ -2841,7 +3320,7 @@ \skvcommaparse{#1}\skv@prova{% \skvexpbracenext\skv@strippointers\skv@prova\skvcurrentkey \skvexpanded{% - \skvifstrcmp{#3}{^skv^}{}{% + \skvifstrcmpTF{#3}{^skv^}{}{% \skv@definedefault{\skvcurrentkey}{\unexpanded{#3}}% }% \skv@appendstyles@b{\skvcurrentkey}\unexpanded{{#2}{#4}}% @@ -2851,12 +3330,12 @@ % \skv@appendstyles@b{<parent.key>}{<styles>}{<parent.key.callback>} \skvrobustdef*\skv@appendstyles@b#1#2#3{% \def\skv@stylelist{}% - \skvkvparse{#2}\skv@provb{% - \def\skv@prova##1=##2=##3\skv@nil{% - \skvxifstrcmp{#1}{##1}{% + \skvkvparse{#2}\skv@prova{% + \ksv@kvosplit\skv@prova{% + \skvxifstrcmpTF{#1}{##1}{% \skv@err{Linking key '##1' to itself}\@ehd }{% - \skvifcsdef{\skv@header##1.@cbk}{}{% + \skvifcsdefTF{\skv@header##1.@cbk}{}{% \skv@err{Style key '##1' is undefined}\@ehd }% }% @@ -2865,10 +3344,9 @@ \skvexpandonce\skvexpanderpointer{\unexpanded{##2}}% }% }% - \expandafter\skv@prova\skv@provb==\skv@nil }% \edef\elt{% - \skvifcsdef{\skv@header#1.@cbk} + \skvifcsdefTF{\skv@header#1.@cbk} {\skvxpandcsonce{\skv@header#1.@cbk}}{}% }% \edef\skv@elt{% @@ -2876,7 +3354,7 @@ {\skvcurrentfamily}{\skvexpandonce\skv@stylelist}}% }% \skvcsedef{\skv@header#1.@cbk}{% - \skvxifstrcmp{\skv@type}{prep}{% + \skvxifstrcmpTF{\skv@type}{prep}{% \skvexpandonce\skv@elt\unexpanded{#3}\skvexpandonce\elt }{% \skvexpandonce\elt\unexpanded{#3}\skvexpandonce\skv@elt @@ -2933,7 +3411,7 @@ } \skvrobustdef*\skv@checkchoice@a#1#2\skv@nil#3#4{% \def\skv@tempa{#2}% - \skvifx\skv@tempa\@empty{% + \skvifxTF\skv@tempa\@empty{% \skv@checkchoice@b#1{#3}{#4}% }{% \skv@checkchoice@c#1#2{#3}{#4}% @@ -2946,7 +3424,7 @@ \else \def\skv@tempa{\endgroup\def#1{#2}}% \fi - \skvifin{,#2,}{,#3,}{% + \skvifinTF{,#2,}{,#3,}{% \ifskv@pl \skvappendtomacro\skv@tempa{\@firstoftwo}% \else @@ -2997,13 +3475,13 @@ \skvrobustdef*\skv@checkchoice@d#1\skv@nil,{\@firstoftwo} \skvrobustdef*\skv@checkchoice@e#1\skv@nil,{\@firstofone} -% \skvifkeydef[<prefs>]{<fams>}{key}{<true>}{<false>} +% \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*\skvifkeydef{\skv@testopt{\skv@ifkeyundef0}{KV}} -\skvrobustdef*\skvifkeyundef{\skv@testopt{\skv@ifkeyundef1}{KV}} +\skvrobustdef*\skvifkeydefTF{\skv@testopt{\skv@ifkeyundef0}\skv@defaultpref} +\skvrobustdef*\skvifkeydefFT{\skv@testopt{\skv@ifkeyundef1}\skv@defaultpref} \skvrobustdef*\skv@ifkeyundef#1[#2]#3#4#5#6{% \skvpushstate\skv@keystate\skv@keydepth \edef\skv@prefs{#2}% @@ -3019,7 +3497,7 @@ \ifskv@kf\skvbreakloop\fi }% \skvexpanded{% - \skvifbool{skv@kf}{% + \skvifboolTF{skv@kf}{% \if0#1% \noexpand\@firstoftwo \else @@ -3039,19 +3517,21 @@ \skvrobustdef*\skv@ifk@yundef{% \skvcommaparse*\skv@fams\skv@prova{% \skv@makeheader\skv@prova - \skvifcsundef{\skv@header\skvcurrentkey.@cbk}{}{% + \skvifcsdefFT{\skv@header\skvcurrentkey.@cbk}{}{% \skv@kftrue\skvbreakloop }% }% } -% \skvifkeyinfamilies[<prefs>]{<fams>}{key}{<true>}{<false>} +% \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. -\skvrobustdef*\skvifkeyinfamilies{% - \skv@testopt{\skv@ifkeyinfamilies0}{KV}% +% +\skvrobustdef*\skvifkeyinfamiliesTF{% + \skv@testopt{\skv@ifkeyinfamilies0}\skv@defaultpref } -\skvrobustdef*\skvifkeynotinfamilies{% - \skv@testopt{\skv@ifkeyinfamilies1}{KV}% +\skvrobustdef*\skvifkeyinfamiliesFT{% + \skv@testopt{\skv@ifkeyinfamilies1}\skv@defaultpref } \skvrobustdef*\skv@ifkeyinfamilies#1[#2]#3#4#5#6{% \skvpushstate\skv@keystate\skv@keydepth @@ -3067,7 +3547,7 @@ \skvcommaparse*\skv@fams\skv@prova{% \skv@makeheader\skv@prova \skvexpanded{% - \skvifcsdef{\skv@header\skvcurrentkey.@cbk}{% + \skvifcsdefTF{\skv@header\skvcurrentkey.@cbk}{% \if0#1% \noexpand\@firstoftwo \else @@ -3084,18 +3564,18 @@ }% \skvpopstate\skv@keystate\skv@keydepth } -% \skvifkeyinfamily{<prefix>/<family>}{<key>} -\skvnewdef*\skvifkeyinfamily#1#2{% - \skvifcsdef{\skvtrimspace{#1}/\skvtrimspace{#2}.@cbk}% +% \skvifkeyinfamilyTF{<prefix>/<family>}{<key>} +\skvnewdef*\skvifkeyinfamilyTF#1#2{% + \skvifcsdefTF{\skvtrimspace{#1}/\skvtrimspace{#2}.@cbk}% } -% \skvifkeyincurrentfamily{<key>} -\skvnewdef*\skvifkeyincurrentfamily#1{% - \skvifcsdef{\skvcurrentpath/\skvtrimspace{#1}.@cbk}% +% \skvifkeyincurrentfamilyTF{<key>} +\skvnewdef*\skvifkeyincurrentfamilyTF#1{% + \skvifcsdefTF{\skvcurrentpath/\skvtrimspace{#1}.@cbk}% } -% \skvifonekeyinfamily{<prefix>/<family>}{<keys>} +% \skvifonekeyinfamilyTF{<prefix>/<family>}{<keys>} % Given a list of keys, test if at least one of them is defined. -% Example: \edef\x{\skvifonekeyinfamily{KV/fam}{keya,keyb,keyc}{T}{F}}. -\skvnewdef*\skvifonekeyinfamily#1#2{% +% Example: \edef\x{\skvifonekeyinfamilyTF{KV/fam}{keya,keyb,keyc}{T}{F}}. +\skvnewdef*\skvifonekeyinfamilyTF#1#2{% \ifnum\numexpr0\skv@ifonekeydef{#1}#2,\@nnil,>\skvz@ \expandafter\@firstoftwo \else @@ -3106,7 +3586,7 @@ \ifx\@nnil#2% \expandafter\@gobble \else - \skvifcsndef{\skvtrimspace{#1}/\skvtrimspace{#2}.@cbk}{+1}{+0}% + \skvifcsdefTF{\skvtrimspace{#1}/\skvtrimspace{#2}.@cbk}{+1}{+0}% \expandafter\skv@ifonekeydef \fi {#1}% @@ -3137,24 +3617,25 @@ % \skvkeyslet[<pref>]{<family>}{<list>} % <list> -> <new keyname>=<old keyname> \skvrobustdef*\skvkeyslet{\skv@testoptb\skv@keyslet} +\skvnewlet\skvkeyinheritance\skvkeyslet \skvnewlet\skvkeylet\skvkeyslet \skvrobustdef*\skv@keyslet#1{% \skvletcs\skv@inikv{\skv@header.@inikv}% - \skvifundef\skv@inikv{}{% + \skvifdefFT\skv@inikv{}{% \expandafter\skv@getkeynames\expandafter{\skv@inikv}\skv@inikeys }% \def\skv@k@yslet##1=##2=##3\skv@nil{% - \skvifcsundef{\skv@header##2.@cbk}{% + \skvifcsdefFT{\skv@header##2.@cbk}{% \skv@err{Key '\skvcurrentpath/##2' is undefined}\@ehd }{% - \skvifcsdef{\skv@header##1.@cbk}{% + \skvifcsdefTF{\skv@header##1.@cbk}{% \skv@err{Key '\skvcurrentpath/##1' is already defined}\@ehd }{}% }% \skvcommaloop{cbk,ndv,fbv}\skv@prova{% \skvcsletcs{\skv@header##1.@\skv@prova}{\skv@header##2.@\skv@prova}% }% - \skvifcsdef{\skv@header##2.@defa}{% + \skvifcsdefTF{\skv@header##2.@defa}{% \edef\skvcurrentkey{##2}% \skv@getdefault\skvcurrentprefix\skvcurrentfamily\skvcurrentkey \skvcurrentvalue @@ -3165,8 +3646,8 @@ }{% \skv@swafalse }% - \skvifundef\skv@inikv{}{% - \skvxifnotin{,\detokenize{##2},}{,\skvoxdetok\skv@inikeys,}{}{% + \skvifdefFT\skv@inikv{}{% + \skvxifinFT{,\detokenize{##2},}{,\skvoxdetok\skv@inikeys,}{}{% \skvcsedef{\skv@header.@inikv}{% \expandafter\skvaddlist\expandafter ,\csname\skv@header.@inikv\endcsname @@ -3176,8 +3657,8 @@ }% \skvcommaloop{ignoredkeys,needini}\skv@prova{% \skvletcs\skv@tempa{\skv@header.@\skv@prova}% - \skvifundef\skv@tempa{}{% - \skvxifnotin{,\detokenize{##2},}{,\skvoxdetok\skv@tempa,}{}{% + \skvifdefFT\skv@tempa{}{% + \skvxifinFT{,\detokenize{##2},}{,\skvoxdetok\skv@tempa,}{}{% \skvcsedef{\skv@header.@\skv@prova}{\skvaddlist,\skv@tempa##1}% }% }% @@ -3194,14 +3675,14 @@ \skv@warn{Key '\skvcurrentpath/#1' has been disabled \MessageBreak You can't set or reset key '#1' at this \MessageBreak late stage. Perhaps you should have set it - \MessageBreak earlier \ifskv@inlatex in \noexpand\documentclass or + \MessageBreak earlier \ifskv@latex in \noexpand\documentclass or \string\usepackage\fi}% } \skvrobustdef*\skv@disabledkeyerror#1{% \skv@err{Key '\skvcurrentpath/#1' has been disabled}% {You can't set or reset key '#1' at this \MessageBreak late stage. Perhaps you should have set it - \MessageBreak earlier \ifskv@inlatex in \noexpand\documentclass or + \MessageBreak earlier \ifskv@latex in \noexpand\documentclass or \string\usepackage\fi}% } \skvrobustdef*\skvdisabledkeysmessagetype#1{% @@ -3229,11 +3710,11 @@ \skvrobustdef*\skvdisablekeys{\skv@testoptb\skv@disablekeys} \skvrobustdef*\skv@disablekeys#1{% \skvcommaparse{#1}\skv@tempa{% - \skvifcsdef{\skv@header\skv@tempa.@cbk}{}{% + \skvifcsdefTF{\skv@header\skv@tempa.@cbk}{}{% \skv@err{Key '\skv@tempa' is undefined: \MessageBreak couldn't be disabled}\@ehd }% - \skvifcsdef{\skv@header\skv@tempa.@defa}{% + \skvifcsdefTF{\skv@header\skv@tempa.@defa}{% \edef\skv@tempb{\noexpand\skv@ordkey{\skv@tempa}[]}% }{% \edef\skv@tempb{\noexpand\skv@ordkey{\skv@tempa}}% @@ -3249,22 +3730,22 @@ % % \skvpresetkeys[<pref>]{<fam>}{<keys>} % \skvgpresetkeys[<pref>]{<fam>}{<keys>} -\skvrobustdef*\skvpresetkeys{\skv@testopt\skv@presetkeys{KV}} +\skvrobustdef*\skvpresetkeys{\skv@testopt\skv@presetkeys\skv@defaultpref} \skvrobustdef*\skv@presetkeys[#1]#2#3{\skvpreposetkeys[#1]{#2}{#3}{}} -\skvrobustdef*\skvgpresetkeys{\skv@testopt\skv@gpresetkeys{KV}} +\skvrobustdef*\skvgpresetkeys{\skv@testopt\skv@gpresetkeys\skv@defaultpref} \skvrobustdef*\skv@gpresetkeys[#1]#2#3{\skvgpreposetkeys[#1]{#2}{#3}{}} -\skvrobustdef*\skvpostsetkeys{\skv@testopt\skv@postsetkeys{KV}} +\skvrobustdef*\skvpostsetkeys{\skv@testopt\skv@postsetkeys\skv@defaultpref} \skvrobustdef*\skv@postsetkeys[#1]#2#3{\skvpreposetkeys[#1]{#2}{}{#3}} -\skvrobustdef*\skvgpostsetkeys{\skv@testopt\skv@gpostsetkeys{KV}} +\skvrobustdef*\skvgpostsetkeys{\skv@testopt\skv@gpostsetkeys\skv@defaultpref} \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} \skvrobustdef*\skv@preposetkeys#1#2{% - \skvifblank{#1}{}{\skv@pr@posetkeys{#1}{preset}}% - \skvifblank{#2}{}{\skv@pr@posetkeys{#2}{postset}}% + \skvifblankTF{#1}{}{\skv@pr@posetkeys{#1}{preset}}% + \skvifblankTF{#2}{}{\skv@pr@posetkeys{#2}{postset}}% } \skvrobustdef*\skv@pr@posetkeys#1#2{% - \skvifcsundef{\skv@header.@#2}{% + \skvifcsdefFT{\skv@header.@#2}{% \skvnormalize{csv}{,}{#1}\skv@tempa \ifskv@cl\expandafter\global\fi \expandafter\def\csname\skv@header.@#2\expandafter @@ -3284,7 +3765,7 @@ \skv@cltrue\skv@testoptb\skv@removepresetkeys } \skvrobustdef*\skv@removepresetkeys#1{% - \skvifcsdef{\skv@header.@preset}{% + \skvifcsdefTF{\skv@header.@preset}{% \expandafter\skv@filterremoveelements\csname\skv@header .@preset\endcsname{#1}\skv@getkeyname }{% @@ -3300,7 +3781,7 @@ \skv@cltrue\skv@testoptb\skv@undefpresetkeys } \skvrobustdef*\skv@undefpresetkeys{% - \skvifcsundef{\skv@header.@preset}{% + \skvifcsdefFT{\skv@header.@preset}{% \skv@err{No preset keys defined for '\skvcurrentprefix/\skvcurrentfamily'}\@ehd }{% @@ -3318,7 +3799,7 @@ \skv@cltrue\skv@testoptb\skv@removepostsetkeys } \skvrobustdef*\skv@removepostsetkeys#1{% - \skvifcsdef{\skv@header.@postset}{% + \skvifcsdefTF{\skv@header.@postset}{% \expandafter\skv@filterremoveelements\csname\skv@header .@postset\endcsname{#1}\skv@getkeyname }{% @@ -3334,7 +3815,7 @@ \skv@cltrue\skv@testoptb\skv@undefpostsetkeys } \skvrobustdef*\skv@undefpostsetkeys{% - \skvifcsundef{\skv@header.@postset}{% + \skvifcsdefFT{\skv@header.@postset}{% \skv@err{No postset keys defined for '\skvcurrentprefix/\skvcurrentfamily'}\@ehd }{% @@ -3356,7 +3837,7 @@ \skv@r@movepreposetkeys{#2}{postset}% } \skvrobustdef*\skv@r@movepreposetkeys#1#2{% - \skvifcsdef{\skv@header.@#2}{% + \skvifcsdefTF{\skv@header.@#2}{% \expandafter\skv@filterremoveelements\csname\skv@header .@#2\endcsname{#1}\skv@getkeyname }{% @@ -3372,7 +3853,7 @@ \skv@cltrue\skv@testoptb\skv@undefpreposetkeys } \skvrobustdef*\skv@undefpreposetkeys{% - \skvifcsundef{\skv@header.@preset}{% + \skvifcsdefFT{\skv@header.@preset}{% \skv@err{No preset keys defined for '\skvcurrentprefix/\skvcurrentfamily'}\@ehd }{% @@ -3453,7 +3934,7 @@ \skv@cltrue\skv@testoptb\skv@saveinitialvaluekeys } \skvrobustdef*\skv@saveinitialvaluekeys#1{% - \skvifcsundef{\skv@header.@needini}{% + \skvifcsdefFT{\skv@header.@needini}{% \edef\skv@tempa{\unexpanded{#1}}% \skvcsvnormalize\skv@tempa \ifskv@cl\expandafter\global\fi @@ -3472,7 +3953,7 @@ \skv@cltrue\skv@testoptb\skv@removesaveinitialvaluekeys } \skvrobustdef*\skv@removesaveinitialvaluekeys#1{% - \skvifcsundef{\skv@header.@needini}{% + \skvifcsdefFT{\skv@header.@needini}{% \skv@err{No save-initial keys defined for '\skvcurrentprefix/\skvcurrentfamily'}\@ehd }{% @@ -3489,7 +3970,7 @@ \skv@cltrue\skv@testoptb\skv@undefsaveinitialvaluekeys } \skvrobustdef*\skv@undefsaveinitialvaluekeys{% - \skvifcsundef{\skv@header.@needini}{% + \skvifcsdefFT{\skv@header.@needini}{% \skv@err{No save-initial keys defined for '\skvcurrentprefix/\skvcurrentfamily'}\@ehd }{% @@ -3502,7 +3983,7 @@ \skvrobustdef*\skvignorekeys{\skv@clfalse\skv@testoptb\skv@ignorekeys} \skvrobustdef*\skvgignorekeys{\skv@cltrue\skv@testoptb\skv@ignorekeys} \skvrobustdef*\skv@ignorekeys#1{% - \skvifcsdef{\skv@header.@ignoredkeys}{% + \skvifcsdefTF{\skv@header.@ignoredkeys}{% \expandafter\skv@filtermergelist\csname \skv@header.@ignoredkeys\endcsname{#1}\skv@getkeyname }{% @@ -3521,7 +4002,7 @@ \skv@cltrue\skv@testoptb\skv@removeignorekeys } \skvrobustdef*\skv@removeignorekeys#1{% - \skvifcsundef{\skv@header.@ignoredkeys}{% + \skvifcsdefFT{\skv@header.@ignoredkeys}{% \skv@err{No ignore keys defined for '\skvcurrentprefix/\skvcurrentfamily'}\@ehd }{% @@ -3538,7 +4019,7 @@ \skv@cltrue\skv@testoptb\skv@undefignorekeys } \skvrobustdef*\skv@undefignorekeys{% - \skvifcsundef{\skv@header.@ignoredkeys}{% + \skvifcsdefFT{\skv@header.@ignoredkeys}{% \skv@err{No ignore keys defined for '\skvcurrentprefix/\skvcurrentfamily'}\@ehd }{% @@ -3568,9 +4049,9 @@ \skvnewlet\skvapendtocallback\skvappendkeycode \skvrobustdef*\skv@prependkeycode#1#2#3{% \edef\skvcurrentkey{\skvtrimspace{#2}}% - \skvifcsdef{\skv@header\skvcurrentkey.@cbk}{% + \skvifcsdefTF{\skv@header\skvcurrentkey.@cbk}{% \skvcsedef{\skv@header\skvcurrentkey.@cbk}{% - \skvifstrcmp{#1}{prep}{% + \skvifstrcmpTF{#1}{prep}{% \skvtrimspace{#3}% \skvexpandcsonce{\skv@header\skvcurrentkey.@cbk}% }{% @@ -3608,7 +4089,7 @@ \skvrobustdef*\skvgetrmkeys{\skv@clfalse\skv@testoptb\skv@getrmkeys} \skvrobustdef*\skvggetrmkeys{\skv@cltrue\skv@testoptb\skv@getrmkeys} \skvrobustdef*\skv@getrmkeys#1{% - \skvifcsdef{\skv@header.@rmkeys}{% + \skvifcsdefTF{\skv@header.@rmkeys}{% \skvletcs#1{\skv@header.@rmkeys}% \ifskv@cl\global\let#1=#1\fi }{% @@ -3641,7 +4122,7 @@ \skv@prepotrue \skvecommaloop*\skv@fams\skvcurrentfamily{% \skv@makeheader\skvcurrentfamily - \skvifcsundef{\skv@header.@#2}{}{% + \skvifcsdefFT{\skv@header.@#2}{}{% \skv@toksa\expandafter\expandafter\expandafter {\csname\skv@header.@#2\endcsname}% \skvexpandtwoargs\skv@setkeys@b{\the\skv@toksa}% @@ -3670,12 +4151,12 @@ \fi % \skv@na can't be anywhere else, not in \skv@setkeys@a. \edef\skv@na{\unexpanded{#2}}% - \skvifempty\skv@na{}{\skvcsvnormalize\skv@na}% + \skvifemptyTF\skv@na{}{\skvcsvnormalize\skv@na}% \edef\skv@tempa{\unexpanded{#1}}% - \skvifempty\skv@tempa{}{\skvkvnormalize\skv@tempa}% + \skvifemptyTF\skv@tempa{}{\skvkvnormalize\skv@tempa}% \def\skv@setkeys@c##1={% - \skvxifin{(}{\detokenize{##1}}{% - \skvxifin{)}{\detokenize{##1}}{% + \skvxifinTF{(}{\detokenize{##1}}{% + \skvxifinTF{)}{\detokenize{##1}}{% \def\skv@ispntkey{00}% \skv@extr@ctpntkey{##1}\skvcurrentkey\skvcurrentvalue \ifx\skvcurrentvalue\@empty @@ -3693,7 +4174,7 @@ \skv@g@tkeyname##1=\skv@nil\skvcurrentkey }% \def\skv@prova####1=####2\skv@nil{% - \skvifcond\if\skv@ispntkey\fi{}{% + \skvifcondTF\if\skv@ispntkey\fi{}{% \edef\skvcurrentvalue{\skvexpandonce{\@gobble####1}}% \ifx\skvcurrentvalue\skv@novaluetoks \skvnovaluetrue @@ -3701,7 +4182,7 @@ \else \skvnovaluefalse \fi - \skvexpbracenext\skvifbraced\skvcurrentvalue{% + \skvexpbracenext\skvifbracedTF\skvcurrentvalue{% \skvvaluebracedtrue }{% % Strip and use pointers from key value: @@ -3738,24 +4219,24 @@ \skvrobustdef*\skv@setkeys@d{% \skv@cnta\@ne \skvletcs\skv@tempa{\skv@header.@ignoredkeys}% - \skvifdef\skv@tempa{% - \skvxifin{,\skvcurrentkey,}{,\skv@tempa,}{% + \skvifdefTF\skv@tempa{% + \skvxifinTF{,\skvcurrentkey,}{,\skv@tempa,}{% \skv@cnta\skvz@ }{% - \skvxifin{,\skvcurrentkey,}{,\skv@na,}{\skv@cnta\skvz@}{}% + \skvxifinTF{,\skvcurrentkey,}{,\skv@na,}{\skv@cnta\skvz@}{}% }% }{% - \skvxifin{,\skvcurrentkey,}{,\skv@na,}{\skv@cnta\skvz@}{}% + \skvxifinTF{,\skvcurrentkey,}{,\skv@na,}{\skv@cnta\skvz@}{}% }% - \skvifnum\skv@cnta=\skvz@{}{% + \skvifnumTF\skv@cnta=\skvz@{}{% \skv@kffalse - \skvifdefbool{skv@prepo}{% + \skvifdefboolTF{skv@prepo}{% \skv@setkeys@e }{% - \skvifdefbool{skv@intry}{% + \skvifdefboolTF{skv@intry}{% \skv@setkeys@e }{% - \skvifdefbool{skv@pl}{% + \skvifdefboolTF{skv@pl}{% \skvecommaloop*\skv@fams\skvcurrentfamily{% \skv@makeheader\skvcurrentfamily \skv@setkeys@e @@ -3776,15 +4257,15 @@ }% }% }% - \skvifdefbool{skv@kf}{% - \ifskv@inpox\skvafterfifi@inneriscond - \ifx\skv@testclass\skv@documentclass\skvafterfi + \skvifdefboolTF{skv@kf}{% + \skvifdefboolTF{skv@inpox}{% + \ifx\skv@userclassorpackage\skv@documentclass\skvafterfi \expandafter\skv@useoption\expandafter{\CurrentOption}% \fi - \fi + }{}% }{% - \skvifdefbool{skv@inpox}{% - \skvifcsdef{\skv@header.@famhandler}{% + \skvifdefboolTF{skv@inpox}{% + \skvifcsdefTF{\skv@header.@famhandler}{% \begingroup \let\elt\skvexpandonce \skvexpanded{\endgroup @@ -3793,21 +4274,21 @@ {\elt\skvcurrentkey}{\elt\skvcurrentvalue}% }% }{% - \skvifcsdef{skv@dox@\@currname @\@currext}{% + \skvifcsdefTF{skv@dox@\@currname @\@currext}{% \skvcsuse{skv@dox@\@currname @\@currext}% }{% - \ifx\@currext\@clsextension\else + \ifx\@currext\@clsextension\else\skvafterfi \let\CurrentOption\skvcurrentkey\@unknownoptionerror \fi }% }% }{% - \skvifdefbool{skv@intry}{% + \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. }{% - \skvifdefbool{skv@st}{% + \skvifdefboolTF{skv@st}{% \ifskv@pl % In this case we've already saved any rm keys. \relax @@ -3815,7 +4296,7 @@ \expandafter\skv@setkeys@f \fi }{% - \skvifcsdef{\skv@header.@famhandler}{% + \skvifcsdefTF{\skv@header.@famhandler}{% \begingroup \let\elt\skvexpandonce \skvexpanded{\endgroup @@ -3834,21 +4315,21 @@ }% } \skvrobustdef*\skv@setkeys@e{% - \skvifcsundef{\skv@header\skvcurrentkey.@cbk}{% + \skvifcsdefFT{\skv@header\skvcurrentkey.@cbk}{% \ifskv@intry\skv@successfalse\fi }{% \skv@kftrue \ifskv@intry\skv@successtrue\fi \ifskvnovalue - \skvifcsdef{\skv@header\skvcurrentkey.@ndv}{% + \skvifcsdefTF{\skv@header\skvcurrentkey.@ndv}{% \skv@err{Key '\skvcurrenttriple' requires - \MessageBreak a user value}\@ehd + \MessageBreak a user value}{Key value needed.}% }{% - \skvifcsdef{\skv@header\skvcurrentkey.@defa}{% + \skvifcsdefTF{\skv@header\skvcurrentkey.@defa}{% \skv@getdefault\skvcurrentprefix\skvcurrentfamily\skvcurrentkey \skvcurrentvalue % Check if the default value is braced: - \skvexpbracenext\skvifnotbraced\skvcurrentvalue{}{% + \skvexpbracenext\skvifbracedFT\skvcurrentvalue{}{% \skvvaluebracedtrue }% }{% @@ -3858,17 +4339,17 @@ }% }% \else - \skvifcsdef{\skv@header\skvcurrentkey.@fbv}{% + \skvifcsdefTF{\skv@header\skvcurrentkey.@fbv}{% \skv@err{Key '\skvcurrenttriple' doesn't - \MessageBreak accept a user value}\@ehd + \MessageBreak accept a user value}{Key value forbidden.}% }{}% \fi - \skvifempty\skvcurrentvalue{}{% + \skvifemptyTF\skvcurrentvalue{}{% \expandafter\skv@replacepointers\expandafter{\skvcurrentvalue}% }% % Use argument type to possibly expand the argument: \def\do##1##2##3{% - \skvifcsdef{\skv@header\skvcurrentkey.@##1arg}{% + \skvifcsdefTF{\skv@header\skvcurrentkey.@##1arg}{% {\noexpand##2}% {\skvexpandcsonce{\skv@header\skvcurrentkey.@##1arg}}% }{% @@ -3879,7 +4360,7 @@ \edef\skv@prova{% % This ordering is important: \do{xx}{\@firstofone}{% - \do{x2}{\expandcstwice}{% + \do{x2}{\skvexpandtwice}{% \do{x1}{\skvexpandonce}{% \do{x0}{\unexpanded}{% \do{}{\unexpanded}{{\noexpand\unexpanded}{####1}}% @@ -3902,7 +4383,7 @@ }% \expandafter\skv@provb\skv@prova\skv@arg@nil \skvcslet{\skv@header\skvcurrentkey.@value}\skvcurrentvalue - \skvifcsdef{\skv@header\skvcurrentkey.@hp}{% + \skvifcsdefTF{\skv@header\skvcurrentkey.@hp}{% \skvexpanded{\skvcslet{\skvexpandcsonce {\skv@header\skvcurrentkey.@hp}}}\skvcurrentvalue }{}% @@ -3946,7 +4427,7 @@ \skvcommaloop*\skv@fams\skv@tempa{% \skv@makeheader\skv@tempa \skvletcs\skv@prova{\skv@header.@rmkeys}% - \skvifdef\skv@prova{% + \skvifdefTF\skv@prova{% \skvexpandbracenext{\skv@setkeys@a[#1]}\skv@prova }{}% }% @@ -3988,14 +4469,14 @@ \skvcommaloop*\skv@fams\skv@tempa{% \skv@makeheader\skv@tempa \skvletcs\skv@tempa{\skv@header.@inikv}% - \skvifundef\skv@tempa{% + \skvifdefFT\skv@tempa{% \skv@err{No 'save initial value' keys defined in family \MessageBreak'\skvcurrentprefix/\skvcurrentfamily'}\@ehd }{% % '\skv@header.@poxkeys' is the list of keys that have been % instantiated as current pacakge options. \skvletcs\skv@tempc{\skv@header.@poxkeys}% - \skvifundef\skv@tempc{% + \skvifdefFT\skv@tempc{% \edef\skv@tempe{% \skvexpandonce\skv@tempe \skvsetkeys[\skvcurrentprefix]{\skvcurrentfamily}% @@ -4006,7 +4487,7 @@ \def\skv@tempd{}% \skvcommaloop*\skv@tempa\skv@tempa{% \expandafter\skv@g@tkeyname\skv@tempa=\skv@nil\skv@tempb - \skvxifin{,\skvoxdetok\skv@tempb,}{,\skvoxdetok\skv@tempc,}{}{% + \skvxifinTF{,\skvoxdetok\skv@tempb,}{,\skvoxdetok\skv@tempc,}{}{% \edef\skv@tempd{% \skvexpandonce\skv@tempd\ifx\skv@tempd\@empty\else,\fi \skvexpandonce\skv@tempa @@ -4028,7 +4509,7 @@ % % \skvdefinekeys*+[<pref>]{<fams>}[<hp>]{<list>} % * -> define only new keys. -% + -> define across the given families. +% + -> define in all the given families. % % The only difference between \skvedefinekeys and \skvdefinekeys is the % value of \endlinechar. @@ -4036,15 +4517,21 @@ % Examples: % % \skvdefinekeys*+[KVA]{fam1,fam2}[thp@]{% -% .ords/{keya,keyb}/{default-a}, -% .cmds/{keyc,keyd}/, +% .initialize after define=true, +% .save initial values, +% .prepend to every key name=X@, +% .ord/{keya,keyb}/{default-a}, +% .cmd/{keyc,keyd}/, % .zcmd/key e/\def\cmde##1{##1}/ % \edef\y{\detokenize\expandafter{\thp@keye}}\def\x##1{#1*key e*##1}, -% .choice/keyf/center/{center.do=\def\x##1{#1*##1},left,right}, -% .zbool/show center/true/\edef\cmd{\ifthp@showcenter Yes\else No\fi}, -% .args/{key1,key2}/{#1/#2}, +% .choice/keyf/center/{center.do=\def\x##1{#1*##1},left,right}/ +% \def\f##1{#1*##1}/\@@warning{Invalid value for keyf}, +% .zbool/show center/true/\edef\cmd{\ifthp@showcenter Yes\else No\fi}/ +% \@@warning{Invalid value for show center}, +% .arg/{key1,key2}/{#1/#2}, % .arg/key3/{#1+#2}, % .exec/\def\x##1{##1}, +% .exec code=\def\y##1{##1}, % } % \skvshowcs{KVA/fam1/keyb.@defa} % \def\keybval{xx} @@ -4056,33 +4543,83 @@ % 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]{% - \skvifvalidboolval{#1}{% + \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]{% - \skvifvalidboolval{#1}{% + \skvifboolvalT{#1}{% \csname skvdfk@saveinitialvalues#1\endcsname }% } -%\skvsetkeys[SKV]{definekeys}{.initialize=false,.save initial values=false} +\skvrobustdef*\skvdfkinitialize{\skvdfk@initializetrue} +\skvrobustdef*\skvdfksaveinitialvalues{\skvdfk@saveinitialvaluestrue} +\skvrobustdef*\skvsetupdefinekeys#1{% + \skvsetkeys[SKV]{definekeys}{#1}% +} +\skvsetupdefinekeys{.initialize=false,.save initial values=false} + +\skvrobustdef*\skvdfkkeytypelet#1{% + \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 + }{% + \skvcsdef{skvdfk@typealias@##1}{##2}% + }% + }% + }% + }% +} +\skvdfkkeytypelet{% + .singleton=.choice, + .exec code=.exec, + .arg=.argx0,.args=.argx0, + .arg expanded once=.argx1, + .arg expanded 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{,} -\skvnewdef*\skvdfk@afterdefinekeys{} -\skvrobustdef*\AfterDefineKeys{\skvgappendtomacro\skvdfk@afterdefinekeys} +\skvnewdef*\skvdfk@afterdefine@hook{} +\skvrobustdef*\skvafterdefinekeys{% + \skvgappendtomacro\skvdfk@afterdefine@hook +} \skvrobustdef*\skvdfk@testopta#1{% \skvifstar{% - \skv@sttrue\skvifplus + \skv@sttrue + \skvifplus {\skv@pltrue\skvdfk@testoptb#1}{\skv@plfalse\skvdfk@testoptb#1}% }{% - \skv@stfalse\skvifplus + \skv@stfalse + \skvifplus {\skv@pltrue\skvdfk@testoptb#1}{\skv@plfalse\skvdfk@testoptb#1}% }% } -\skvrobustdef*\skvdfk@testoptb#1{\skv@testopt{\skvdfk@t@stoptb{#1}}{KV}} +\skvrobustdef*\skvdfk@testoptb#1{% + \skv@testopt{\skvdfk@t@stoptb{#1}}\skv@defaultpref +} \skvrobustdef*\skvdfk@t@stoptb#1[#2]#3{% - \skvxifin{,}{\detokenize{#2}}{% + \skvxifinTF{,}{\detokenize{#2}}{% \skv@err{Only one prefix is allowed when calling \MessageBreak \noexpand\skvdefinekeys or similar commands, \MessageBreak but you gave '#2'}\@ehd @@ -4092,7 +4629,7 @@ % macro \skvdefinekeys. \edef\skv@checkkeyexist{\ifskv@st00\else01\fi}% \edef\skvdfk@pref{#2}% - \skvxifin{,}{\detokenize{#3}}{% + \skvxifinTF{,}{\detokenize{#3}}{% \edef\skvdfk@fams{#3}% \skvcsvnormalize\skvdfk@fams }{% @@ -4102,264 +4639,338 @@ \skv@testopt#1{userhp@}% }% } -\skvnewnumbers{skvdfk@depth} -\skvrobustdef*\skv@pushdefinekeys{% - \skvpushfunctions\skvdefinekeys{% - \do\skvdfk@pref\do\skvdfk@fams\do\skvdfk@currlist\do\skv@accumulated - \do\skv@acc@mulated\do\skv@igkeys\do\skvdfk@keys\do\skvdfk@keyvals - \do\skv@itemfour\do\skv@itemfive\do\skv@checkkeyexist\do\skv@hp - \do\skv@type\do\skv@typenr\do\skv@default\do\skv@isarg - \do\ifskvdfk@initialize\do\ifskvdfk@saveinitialvalues\do\ifskv@st - \do\ifskv@pl\do\skvcurrentprefix\do\skvcurrentfamily\do\skvcurrentkey - }\skvdfk@depth -} +% \skvedefinekeys has no stack, since everything is done in a local group. +% It is \skvmakekeys that has a stack. \skvrobustdef*\skvedefinekeys{% - \skv@pushdefinekeys \begingroup \endlinechar\m@ne - \skvdfk@testopta\skv@definekeys + \skvdfk@testopta\skv@definekeys@a } \skvrobustdef*\skvdefinekeys{% - \skv@pushdefinekeys \begingroup - \skvdfk@testopta\skv@definekeys + \skvdfk@testopta\skv@definekeys@a } -\skvrobustdef*\skv@definekeys[#1]#2{% - \skvexpanded{\endgroup - \skvcmdexitloop{\skv@checkkeyexist\skvdfk@pref\skvdfk@fams}% - \skvboolexit\ifskv@pl - }% +\skvrobustdef*\skv@definekeys@a[#1]#2{% \skvindeftrue + \def\skv@validtypes{% + .ord,.cmd,.zcmd,.bool,.zbool,.tog,.ztog,.choice,.choice*,% + .exec,.afterdef,.initialize,.saveini,.argx0,.argx1,.argx2,.argxx,% + .preptokey,.apptokey,.preptocode,.apptocode% + }% + \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{}% \edef\skv@hp{#1}% \skvdespacecontent\skv@hp - \def\skv@accumulated{}% + \def\skv@accumulateonfams{}% \skv@makeprefix\skvdfk@pref \edef\skvdfk@currlist{\skvkeepdoubleslashnormalize{#2}}% - \def\skv@d@finekeys##1{% + \def\skv@definekeys@b##1{% \skv@makeheader{##1}% - \def\skv@acc@mulated{}% + \def\skv@accumulateonkeys{}% \def\skvdfk@keys{}% \def\skvdfk@keyvals{}% - \expandafter\skv@d@f@nekeys\expandafter{\skvdfk@currlist}% + \skvexpbracenext\skv@definekeys@c\skvdfk@currlist }% % If the plus variant is not specified, just take and use the first % family. - \skvifdefbool{skv@pl}{% + \skvifdefboolTF{skv@pl}{% \skvcommaloop*\skvdfk@fams\skv@tempa{% - \expandafter\skv@d@finekeys\expandafter{\skv@tempa}% + \skvexpbracenext\skv@definekeys@b\skv@tempa }% }{% \def\skv@prova##1,##2\skv@nil{% - \skv@d@finekeys{##1}% + \skv@definekeys@b{##1}% }% \expandafter\skv@prova\skvdfk@fams,\skv@nil }% - \skv@accumulated - \skvpopfunctions\skvdefinekeys\skvdfk@depth + \edef\skv@accumulateonfams{% + \skvxonce\skv@accumulateonfams + \skvxonce\skvdfk@afterdefine@hook\relax + }% + \expandafter\endgroup\skv@accumulateonfams \skvindeffalse - \skvdfk@afterdefinekeys\relax - \def\skvdfk@afterdefinekeys{}% + % 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 + \skvdfk@initializefalse\skvdfk@saveinitialvaluesfalse + \fi } -\skvrobustdef*\skv@d@f@nekeys#1{% +\skvrobustdef*\skv@definekeys@c#1{% \edef\skv@igkeys{% - \skvifcsdef{\skv@header.@ignoredkeys}{% + \skvifcsname\skv@header.@ignoredkeys\then \skvexpandcsonce{\skv@header.@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{% - \let\skv@gobble\relax - \edef\skv@type{\unexpanded{##1}}% - % Take the default early: it is needed in splitting multiple keys of - % the same type. In this case, the default value will not change - % until the splitting is completed. - \edef\skv@default{\skvexpandonce{\@gobble##3}}% - \def\skv@isarg{01}% - \def\skv@prova####1{% - \def\skv@prova########1####1########2########3\skv@nil{% - \def\skv@typenr{########2}% - \ifx\skv@typenr\skv@nnil - \skv@err{Invalid key type '####1'}\@ehd - \else - \ifnum\skv@typenr>6\relax - \ifnum\skv@typenr<11\relax - \def\skv@isarg{00}% - \fi - \fi - \fi - }% - \skv@prova .ord{0}.cmd{1}.zcmd{2}.bool{3}.zbool{4}.choice{5}% - .exec{6}.arg{7}.arg expanded{8}.arg expanded once{9}% - .arg expanded twice{10}.ords{11}.cmds{12}.zcmds{13}.bools{14}% - .zbools{15}.choices{16}.args{17}####1{\skv@nil}\skv@nil - }% - \expandafter\skv@prova\expandafter{\skv@type}% - \skvxifin{,\skv@typenr,}{,11,12,13,14,15,16,17,}{% - % Accumulate multiple keys of the same type: - \def\skv@prova####1s{\def\skv@type{####1}}% - \expandafter\skv@prova\skv@type - \skvcommaparse{##2}\skv@tempa{% - \skvexpanded{% - \noexpand\skv@splita - \skv@type/\skv@tempa/\skvexpandonce\skv@default/% - \unexpanded{##4/##5/##6/##7/##8/##9}\noexpand\skv@split@nil - }% - }% - % Skip the rest of \skv@splitb: - \let\skv@gobble\skv@gobbletoend + \skvxifinTF{\skv@hashchar}{\detokenize{##2}}{% + \skv@err{Key name(s) '\detokenize{##2}' contain hash character}\@ehd }{% - \skvifnum\skv@typenr=6{% - ##2% - \let\skv@gobble\skv@gobbletoend - }{% - % There may be multiple keys in ##2. So keep findpointers here, - % where multiple keys would have been split into separate units. - % For example, we can't check for ignored keys without first - % stripping the pointers: - \skv@strippointers{##2}\skvcurrentkey - \skvxifin{,\skvoxdetok\skvcurrentkey,}{,\skvoxdetok\skv@igkeys,}{% - \let\skv@gobble\skv@gobbletoend - }{% - \if\skv@isarg - \skvdfk@definearg\skv@type\skvcurrentkey\skv@default - \let\skv@gobble\skv@gobbletoend - \else - \let\skv@gobble\relax - \fi + % In case we have, eg, .exec=\def\x{?} instead of .exec/\def\x{?}: + \skvxifinTF{=}{\detokenize{##1}}{% + \skv@kvsplit{##1}{% + \edef\skv@type{\skvtrimspace{####1}}% + \edef\skv@itemtwo{\skvtrimspace{####2}}% }% + }{% + \edef\skv@type{\unexpanded{##1}}% + \edef\skv@itemtwo{\unexpanded{##2}}% }% }% - \skv@gobble + \skvifcsname skvdfk@typealias@\skv@type\then + \edef\skv@type{\skvcsuse{skvdfk@typealias@\skv@type}}% + \fi + \edef\skv@default{\skvexpandonce{\@gobble##3}}% + % To avoid mixing parameter characters in \skv@prova: + \edef\skv@rest{\unexpanded{{##4}/{##5}/{##6}/{##7}/{##8}/{##9}}}% + \skvexpbracenext\skv@definekeys@d\skv@type + }% + \def\skv@splitc##1/##2/##3/##4/##5/##6/##7/##8/##9\skv@split@nil{% \edef\skv@itemfour{\unexpanded{##4}}% \edef\skv@itemfive{\unexpanded{##5}}% - \skvxifin{\skv@hashchar}{\detokenize{##2}}{% - \skv@err{Key name '\detokenize{##2}' contains hash character}\@ehc - }{}% - \if\skv@checkkeyexist - \skvifcsdef{\skv@header\skvcurrentkey.@cbk}{% - \skv@err{Key '\skvcurrenttriple' already exists}\@ehd - }{}% - \fi - \ifnum\skv@typenr=5\relax - \edef\skv@prova{% - 0\ifx\skv@itemfour\@empty 1\else\ifx\skv@itemfour\skv@rej 1\fi\fi - }% - \ifcase\skv@prova\relax - \def\skv@altlista{}\def\skv@altlistb{}% - % \skv@itemfour is need here to hide unbalanced conditionals in ##4: - \expandafter\skv@getaltlist\expandafter{\skv@itemfour}% - \else - \skv@err{Empty alternate list for choice key '\skvcurrentkey'}\@ehd + \edef\skv@itemsix{\unexpanded{##6}}% + \skvifplaswTF\skv@isarg{% + \skvdfk@definearg{##1}{##2}{##3}% + }{% + \if\skv@checkkeyexist + \skvifcsname\skv@header##2.@cbk\then + \skv@err{Key '\skvcurrenttriple' already exists}\@ehd + \fi \fi - \fi - \edef\skvdfk@keys{\skvaddlist,\skvdfk@keys\skvcurrentkey}% - \skvxifboolval{\skvexpandonce\skv@default}\in@true\in@false - \edef\skvdfk@keyvals{% - \skvaddlist,\skvdfk@keyvals - % If a key has no default, then it can't be initialized. An empty - % default value should be indicated with a slash, eg, keya below: - % .cmd/keya/, .bool/keyb/true. - \expandafter\skv@ifrejorna\expandafter{\skv@default}{}{% - \skvcurrentkey=\skvifdefbool{in@}{false}{\skvxonce\skv@default}% - }% - }% - \edef\skv@acc@mulated{% - \skvexpandonce\skv@acc@mulated - \skvnoexpandcs{skv\expandafter\@gobble\skv@type key}% - \ifnum\skv@typenr=5*\fi - \ifnum\skv@typenr>2\ifnum\skv@typenr<6+\fi\fi - [\skvcurrentprefix]{\skvcurrentfamily}% - % ##2 should be inserted below instead of \skvcurrentkey, because - % \skvcurrentkey has had any possible pointer stripped: - \ifnum\skv@typenr>0\ifnum\skv@typenr<6[\skv@hp]\fi\fi - {##2}% - \ifnum\skv@typenr=5% no \relax here. - [\unexpanded{\skvuserinput\skvorder}]{\skvexpandonce\skv@altlista}% + \if\skv@ischoice + \skv@ifcmdnut\skv@itemfour{% + \skv@err{Empty nominations (state pattern) for + \MessageBreak choice key '##2'}\@ehd + }{}% \fi - % default: - \expandafter\skv@ifrejorna\expandafter{\skv@default}{}{% - [{\skvexpandonce\skv@default}]% + \edef\skvdfk@keys{\skvaddlist,\skvdfk@keys##2}% + \skvxifboolvalTF{\skvexpandonce\skv@default}\in@true\in@false + \edef\skvdfk@keyvals{% + \skvaddlist,\skvdfk@keyvals + \skv@ifcmdrejordotna\skv@default{}{% + ##2=\skvifdefboolTF{in@}{false}{\skvexpandonce\skv@default}% + }% }% - {% - % Key callback. If choice key, then the callback is item 5, - % otherwise it's item 4: - \skvifnum\skv@typenr=5{% - \skvifx\skv@itemfive\skv@rej{}{\skvexpandonce\skv@itemfive}% - \skv@executealt{########1}{\skvexpandonce\skv@altlistb}% - }{% - \skvifx\skv@itemfour\skv@rej{}{\skvexpandonce\skv@itemfour}% + \if\skv@isboolorchoice + \if\skv@ischoice + \let\skv@altact\skv@itemsix + \else + % bool or tog: + \let\skv@altact\skv@itemfive + \fi + \skv@ifcmdnut\skv@altact{\let\skv@altact\skvkeyvalueerror}{}% + \fi + \iftypeis.choice*\then + \def\skv@prova####1*{\def\skv@typeb{####1}}% + \expandafter\skv@prova\skv@type + \else + \let\skv@typeb\skv@type + \fi + % Remove leading dot (.): + \edef\skv@typeb{\expandafter\@gobble\skv@typeb}% + \edef\skv@accumulateonkeys{% + \skvexpandonce\skv@accumulateonkeys + \skvnoexpandcs{skv\skv@typeb key}% + \iftypeis.choice*\then*\fi + \if\skv@isboolorchoice+\fi + [\skvcurrentprefix]{\skvcurrentfamily}% + \if\skv@needhp[\skv@hp]\fi + {##2}% + \if\skv@ischoice + [\unexpanded{\skvuserinput\skvorder}]{\skvxonce\skv@itemfour}% + \fi + % default: + \skv@ifcmdrejordotna\skv@default{}{[{\skvxonce\skv@default}]}% + {% Key callback: + \skvxonce\skv@prependtoeverycallback + % If choice key, then the callback is item 5, otherwise + % it's item 4: + \if\skv@ischoice + \skv@ifcmdnut\skv@itemfive{}{\skvxonce\skv@itemfive}% + \else + \skv@ifcmdnut\skv@itemfour{}{\skvxonce\skv@itemfour}% + \fi + \skvxonce\skv@appendtoeverycallback }% + % Second branch of callback for '+' variants, now used for all + % boolean and choice keys: + \if\skv@isboolorchoice{\skvexpandonce\skv@altact}\fi }% - % Second branch of callback for '+' variants, now used for all - % boolean and choice keys: - \ifnum\skv@typenr>2\ifnum\skv@typenr<6{\skvkeyvalueerror}\fi\fi }% - \skv@gobble@nil }% \skvexpanded{\skvparselist{\skv@keyparser}}{#1}\skv@prova{% \expandafter\skv@splita\skv@prova /^skv^/^skv^/^skv^/^skv^/^skv^/^skv^/^skv^/^skv^\skv@split@nil }% - % 1. \skv@accumulated is a two-layer stack: there're loops on families - % and keys. + % 1. \skv@accumulateonfams is a two-layer stack: there're loops on + % families and keys. % 2. To save initial values of keys, the key names should be % entered by \skvsaveinitialvaluekeys in 'needini' list. This is % the case even when the boolean '.initialize' is true. See below. % 3. The boolean '.save initial values' is the one that will invoke % \skvsaveinitialvaluekeys below. - \edef\skv@accumulated{% - \skvexpandonce\skv@accumulated % looping on families - \skvifdefbool{skvdfk@saveinitialvalues}{% - \noexpand\skvsaveinitialvaluekeys[\skvcurrentprefix]% - {\skvcurrentfamily}{\skvexpandonce\skvdfk@keys}% - }{}% - \skvexpandonce\skv@acc@mulated % looping on keys - \skvifdefbool{skvdfk@initialize}{% - \noexpand\skvsetkeys[\skvcurrentprefix]% - {\skvcurrentfamily}{\skvexpandonce\skvdfk@keyvals}% - }{}% + \def\@elt{% + [\skvcurrentprefix]{\skvcurrentfamily}{\skvxonce\skvdfk@keyvals}% + }% + \edef\skv@accumulateonfams{% + \skvexpandonce\skv@accumulateonfams + \ifskvdfk@saveinitialvalues + \noexpand\skvsaveinitialvaluekeys\@elt + \fi + \skvexpandonce\skv@accumulateonkeys + \ifskvdfk@initialize + \noexpand\skvsetkeys\@elt + \fi + }% +} +\skvrobustdef*\skv@definekeys@d#1{% + \skvxifinFT{,#1,}{,\skv@validtypes,}{% + \skv@err{Invalid key type '#1' in \string\skvdefinekeys}\@ehd + }{% + \@tempswatrue + \iftypeis.exec\then + \@tempswafalse + \edef\skv@accumulateonkeys{% + \skvexpandonce\skv@accumulateonkeys\skvexpandonce\skv@itemtwo + }% + \else + \iftypeis.initialize\then + \@tempswafalse + \skv@ifcmdnut\skv@itemtwo{% + \edef\skv@itemtwo{true}% + }{% + \skvexpbracenext\skvifboolvalT\skv@itemtwo\relax + }% + \csname skvdfk@initialize\skv@itemtwo\endcsname + \edef\skv@accumulateonfams{% + \skvexpandonce\skv@accumulateonfams + \noexpand\csname skvdfk@initialize\skv@itemtwo\endcsname + }% + \else + \iftypeis.saveini\then + \@tempswafalse + \skv@ifcmdnut\skv@itemtwo{% + \edef\skv@itemtwo{true}% + }{% + \skvexpbracenext\skvifboolvalT\skv@itemtwo\relax + }% + \csname skvdfk@saveinitialvalues\skv@itemtwo\endcsname + \edef\skv@accumulateonfams{% + \skvexpandonce\skv@accumulateonfams + \noexpand\csname skvdfk@saveinitialvalues\skv@itemtwo + \endcsname + }% + \else + \iftypeis.preptokey\then + \@tempswafalse + \let\skv@prependtoeverykeyname\skv@itemtwo + \else + \iftypeis.apptokey\then + \@tempswafalse + \let\skv@appendtoeverykeyname\skv@itemtwo + \else + \iftypeis.preptocode\then + \@tempswafalse + \let\skv@prependtoeverycallback\skv@itemtwo + \else + \iftypeis.apptocode\then + \@tempswafalse + \let\skv@appendtoeverycallback\skv@itemtwo + \fi + \fi + \fi + \fi + \fi + \fi + \fi + \skvifdefboolTF{@tempswa}{% + % Leave these tests here, so that they aren't repeated for each + % key in the next loop: + \def\do##1{\def##1{01}}% + \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}% + }{% + \skvifinTF{,#1,}{,.bool,.zbool,.tog,.ztog,}{% + \def\skv@isboolorchoice{00}% + \def\skv@needhp{00}% + }{% + \skvifinTF{,#1,}{,.cmd,.zcmd,}{% + \def\skv@needhp{00}% + }{% + \skvifinTF{,#1,}{,.argx0,.argx1,.argx2,.argxx,}{% + \def\skv@isarg{00}% + }{}% + }% + }% + }% + \skvcommaprocess*\skv@itemtwo\skv@tempa{% + \skvexpbracenext\skv@strippointers\skv@tempa\skvcurrentkey + \edef\skvcurrentkey{% + \skv@prependtoeverykeyname\skvcurrentkey + \skv@appendtoeverykeyname + }% + \let\do\skvoxdetok + \skvxifinTF{,\do\skvcurrentkey,}{,\do\skv@igkeys,}{}{% + \edef\do{% + \noexpand\skv@splitc#1/\skvcurrentkey/% + {\skvexpandonce\skv@default}/\skvexpandonce\skv@rest + }% + \do\skv@split@nil + }% + }% + }{% + \skvifinFT{,#1,} + {,.preptokey,.apptokey,.preptocode,.apptocode,}{}{% + \let\skv@tempa\skv@itemtwo + \skvexpbracenext\skv@strippointers\skv@itemtwo\skv@itemtwo + \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 + \fi + }% + }% }% } % % Assigning arguments within \skvdefinekeys: % -% Eg, .args/{key1,key2}/{#1/#2} +% Eg, .arg/{key1,key2}/{#1/#2} % \skvrobustdef*\skvdfk@definearg#1#2#3{% \begingroup - \toks@\expandafter{#3}% \def\skv@prova.arg##1\skv@nil{% - \if\relax\detokenize{##1}\relax - \def\skv@prova{x0}% - \else - \edef\skv@provb{\skvtrimspace{##1}}% - \def\skv@prova####1{% - \def\skv@prova########1####1########2########3\skv@nil{% - \def\skv@prova{########2}% - \ifx\skv@prova\skv@nnil - \def\skv@prova{x0}% - \fi - }% - \skv@prova - expanded{xx}expand once{x1}expand twice{x2}####1{\skv@nil}\skv@nil - }% - \expandafter\skv@prova\expandafter{\skv@provb}% - \fi + \edef\skv@prova{\skvtrimspace{##1}}% + }% + \skv@prova#1\skv@nil + \edef\skv@accumulateonkeys{% + \skvexpandonce\skv@accumulateonkeys + \skvcsedef{\skv@header#2.@\skv@prova arg}{% + \noexpand\unexpanded{\unexpanded{#3}}% + }% }% - \expandafter\skv@prova#1\skv@nil - \skvcsedef{\skv@header#2.@\skv@prova arg}{\the\toks@}% - \expandafter\skvaftergroupdef - \csname\skv@header#2.@\skv@prova arg\endcsname\endgroup + \skvaftergroupdef\skv@accumulateonkeys\endgroup } %+++++++++++++++++++++++ Keys for \skvmakekeys +++++++++++++++++++++++% % Example: % \skvmakekeys[ -% prefix=KVA, families={fam1,fam2}, hp=thp@, all new, -% define in all families, initialize=true, endlinechar=-1 +% .prefix=KVA, .families={fam1,fam2}, .hp=thp@, .all new, +% .define in all families, .initialize=true, .endlinechar=-1 % ]{% -% .ords/{keya,keyb}/{default-a}, -% .cmds/{keyc,keyd}/, +% .ord/{keya,keyb}/{default-a}, +% .cmd/{keyc,keyd}/, % .zcmd/key e/\def\cmde##1{##1}/ % \edef\y{\detokenize\expandafter{\thp@keye}}\def\x##1{#1*key e*##1}, % .choice/keyf/center/{center.do=\def\x##1{#1*##1},left,right}, @@ -4370,34 +4981,35 @@ % \skvsetkeys[KVA]{fam1}{keyb=.expand once{\keybval}} \skvedefinekeys*[SKV]{makekeys}[skvmk@]{% - .ords/{.new,.all new,.all are new}/true/ - \edef\skvmk@allnew{\skvifstrcmp{#1}{true}{00}{01}} + .ord/{.new,.all new,.all are new}/true/ + \edef\skvmk@allnew{0\skvifstrcmpTF{#1}{true}{0}{1}} , - .ords/{.initialize,.initialize after define}/true/ - \skvifvalidboolval{#1}{% + .ord/{.initialize,.initialize after define,.initialize keys after define} + /true/ + \skvifboolvalT{#1}{% \csname skvdfk@initialize#1\endcsname }% , - .ord/.save initial values/true/ - \skvifvalidboolval{#1}{% + .ord/.save initial values,.save initial values of keys/true/ + \skvifboolvalT{#1}{% \csname skvdfk@saveinitialvalues#1\endcsname }% , - .ords/{.endlinechar,.endline character}/13/ + .ord/{.endlinechar,.endline character}/13/ \def\skvmk@endlinechar{#1}, - .ords/{.define in all families,.in all families}/true/ - \edef\skvmk@inallfams{\skvifstrcmp{#1}{true}{00}{01}} + .ord/{.define in all families,.in all families}/true/ + \edef\skvmk@inallfams{0\skvifstrcmpTF{#1}{true}{0}{1}} , - .ord/.prefix/KV/ + .ord/.prefix/\skv@defaultpref/ \skviflacus#1\then - \def\skvmk@pref{KV}% + \let\skvmk@pref\skv@defaultpref \else \edef\skvmk@pref{#1}% \skvstripouterbraces{2}\skvmk@pref \fi , - .ords/{.holder prefix,.hp}/userhp@/\edef\skvmk@hp{#1}, - .ords/{.family,.families}/^skv^/ + .ord/{.holder prefix,.hp}/userhp@/\edef\skvmk@hp{#1}, + .ord/{.family,.families}/\@nil/ \skviflacus#1\then \skv@err{Key family is empty\on@line}\@ehd \else @@ -4406,6 +5018,7 @@ \fi , } + % Default settings for keys of \skvmakekeys. Presetting keys will be % inefficient here, since many of the keys have complements. It will be % necessary to include all the complements in the preset list, but doing @@ -4423,19 +5036,17 @@ \do\ifskvdfk@saveinitialvalues }\skv@makekeysdepth \skvsetkeys[SKV]{makekeys}{#1}% - \ifx\skvmk@fams\skv@rej + \ifx\skvmk@fams\@nnil \skv@err{No family specified for \string\skvmakekeys}\@ehd \fi - % Push the stack of \skvdefinekeys: - \skv@pushdefinekeys % The following \begingroup is ended in \skv@definekeys: \begingroup \skvexpanded{% \endlinechar=\skvmk@endlinechar\relax - \skvdfk@testopta\skv@definekeys + \skvdfk@testopta\skv@definekeys@a \if\skvmk@allnew*\fi\if\skvmk@inallfams+\fi [\skvmk@pref]{\skvmk@fams}% - [\ifx\skvmk@hp\@empty skvhp@\else\skvmk@hp\fi]% + [\ifx\skvmk@hp\@empty userhp@\else\skvmk@hp\fi]% }% {#2}% \skvpopfunctions\skvmakekeys\skv@makekeysdepth @@ -4444,52 +5055,19 @@ \skvrobustdef*\skvkeyvalueerror{% \skv@getinnoval\CurrentOption \skv@err{Erroneous value '\skv@ival' for key or option - \MessageBreak'\skvcurrentkey'} - {Invalid key value encountered.}% -} -\skvrobustdef*\skv@getaltlist#1{% - \begingroup - \def\skv@g@taltlist##1.do=##2.do=##3\skv@nil{% - \edef\skv@prova{\skvtrimspace{##1}}% - \edef\skv@provb{\skvoxdetok\skv@prova{\skvtrimspace{##2}}}% - \skvaddtolist*\skv@altlista\skv@prova - \skvaddtolist*\skv@altlistb\skv@provb - }% - \skvcommaparse{#1}\skv@prova{% - \expandafter\skv@g@taltlist\skv@prova.do=.do=\skv@nil - }% - \skvexpanded{\endgroup - \skvcmdexitloop{\skv@altlista\skv@altlistb}% - }% -} -\skvrobustdef*\skv@executealt#1#2{% - \edef\skv@prova{\skvtrimspace{#1}}% - \edef\skv@prova{\skvoxdetok\skv@prova}% - \def\skv@provb##1{% - \def\skv@provb####1##1####2####3\skv@nil{% - \edef\skv@prova{\unexpanded{####2}}% - \skvifx\skv@prova\skv@nnil{% - \skv@err{No alternate list match for key '\skvcurrentkey'}\@ehd - }{% - ####2% - }% - }% - }% - \expandafter\skv@provb\expandafter{\skv@prova}% - \skvexpandsecond{\skv@provb#2}\skv@prova{\skv@nil}\skv@nil + \MessageBreak'\skvcurrentkey'}{Invalid key value encountered.}% } \skvrobustdef*\skv@getinnoval#1{% \begingroup - \def\skv@prova##1=##2=##3\skv@nil{% + \skv@kvosplit{#1}{% \edef\skv@provb{\detokenize{##2}}% - \skvifx\skv@provb\@empty{% + \skvifxTF\skv@provb\@empty{% \def\skv@ival{???}% }{% \skv@getbasetoks{30}\skv@provb\skv@ival }% }% - \expandafter\skv@prova#1==\skv@nil \skvaftergroupdef\skv@ival\endgroup } % \skv@getbasetoks{<nr>}{<toks.cmd>}{<result.cmd>} @@ -4499,7 +5077,7 @@ \def#3{}\@tempcnta\skvz@ \def\do##1{% \def\skv@prova{##1}% - \skvifx\skv@prova\skv@nnil{}{% + \skvifxTF\skv@prova\skv@nnil{}{% \advance\@tempcnta\@ne \ifnum\@tempcnta<#1\relax \edef#3{#3\ifx\next\@sptoken\@space\fi##1}% @@ -4527,7 +5105,9 @@ % } % \skvsetkeys[KV]{fam}{unknownkey=val} % -\skvrobustdef*\skvunknownkeyhandler{\skv@testopt\skv@unknownkeyhandler{KV}} +\skvrobustdef*\skvunknownkeyhandler{% + \skv@testopt\skv@unknownkeyhandler\skv@defaultpref +} % For each prefix and family, this will define the functions % \<prefix>/<family>/.@famhandler of 4 parameters (prefix, family, % key name, current value). @@ -4547,27 +5127,26 @@ % .prefix=KVA,.families={fam1,fam2},.set in all families, % .save rm keys % ]{% -% key1,key2 +% key1=value1, key2=value2 % } - \skvmakekeys[ .prefix=SKV,.family=usekeys,.hp=skvuk@,.endlinechar=-1 ]{% - .ords/{.save rm,.save rm keys,.save unknown keys}/true/ - \edef\skvuk@saverm{\skvifstrcmp{#1}{true}{00}{01}} + .ord/{.save rm,.save rm keys,.save unknown keys}/true/ + \edef\skvuk@saverm{\skvifstrcmpTF{#1}{true}{00}{01}} , - .ords/{.set in all families,.in all families}/true/ - \edef\skvuk@inallfams{\skvifstrcmp{#1}{true}{00}{01}} + .ord/{.set in all families,.in all families}/true/ + \edef\skvuk@inallfams{\skvifstrcmpTF{#1}{true}{00}{01}} , - .ord/.prefix/KV/ + .ord/.prefix/\skv@defaultpref/ \skviflacus#1\then - \def\skvuk@pref{KV}% + \let\skvuk@pref\skv@defaultpref \else \edef\skvuk@pref{#1}% \skvstripouterbraces{2}\skvuk@pref \fi , - .ords/{.family,.families}/^skv^/ + .ord/{.family,.families}/\@nil/ \skviflacus#1\then \skv@err{Key family is empty\on@line}\@ehd \else @@ -4575,10 +5154,22 @@ \skvstripouterbraces{2}\skvuk@fams \fi , + .ord/{.path,paths}/\@nil/ + \skvifblankTF{#1}{% + \skv@err{Key family is empty\on@line}\@ehd + }{% + \edef\skvuk@paths{#1}% + \skvstripouterbraces{2}\skvuk@paths + \skvexpbracenext\skv@slashsplit\skvuk@paths{% + \skvsetkeys[SKV]{usekeys}{.prefix=##1,.family=##2}% + }% + }% + , } + % Default settings for keys of \skvusekeys: \skvsetkeys[SKV]{usekeys}{% - .prefix,.family=^skv^,.set in all families=false,.save rm=false + .prefix,.family=^skv^,.set in all families=false,.save rm=false% } \skvrobustdef*\skvusekeys{\skv@testopt\skv@usekeys{}} @@ -4587,7 +5178,7 @@ \do\skvuk@fams\do\skvuk@pref\do\skvuk@inallfams\do\skvuk@saverm }\skv@usekeysdepth \skvsetkeys[SKV]{usekeys}{#1}% - \ifx\skvuk@fams\skv@rej + \ifx\skvuk@fams\@nnil \skv@err{No family specified for \string\skvusekeys}\@ehd \fi \skvexpanded{% @@ -4600,34 +5191,41 @@ %++++++++++ Utilities for handlers of the macro \directkeys +++++++++++% \skvnewlet\handlereov\relax -\skvrobustdef*\directkeys{\skv@testst\dirkeys@parse} +% 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@} + +\skvrobustdef*\directkeys{\skv@testst\skv@dirkeys@parse@a} \skvnewlet\dirkeys\directkeys -\skvrobustdef*\dirkeys@parse{% +\skvrobustdef*\skv@dirkeys@parse@a{% \begingroup \ifskv@tempst\endlinechar\m@ne\fi - \dirkeys@parse@a + \skv@dirkeys@parse@b } -\skvrobustdef*\dirkeys@parse@a#1{% +\skvrobustdef*\skv@dirkeys@parse@b#1{% \endgroup - \skvpushstate\dirkeys@state\dirkeys@depth - \indirkeystrue + \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{}% \def\dirkeys@holderprefixtoks{}% \dirkeys@saveunknownkeysfalse + \skvdfk@initializefalse + \skvdfk@saveinitialvaluesfalse \edef\skv@tempa{\unexpanded{#1}}% \skvstripouterbraces{2}\skv@tempa \skvkvnormalize\skv@tempa - \def\dirkeys@do##1=##2=##3\dirkeys@nil{% + \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 % we have a nested \dirkeys: - \expandafter\skvifx\skv@car##1x\car@nil\dirkeys{% - \skvifempty\skv@tempa{% + \expandafter\skvifxTF\skv@car##1x\car@nil\dirkeys{% + \skvifemptyTF\skv@tempa{% ##1\relax }{% \skv@err{Something wrong with use of \string\dirkeys: @@ -4635,20 +5233,20 @@ }% }{% \skv@ensurehandlerdot{##1}% - \skvifcsdef{dirkeys@handler@##1}{% + \skvifcsdefTF{dirkeys@handler@##1}{% \csname dirkeys@handler@##1\expandafter\endcsname \skv@tempa\handlereov }{% \skv@err{Unknown handler '\detokenize{##1}'\MessageBreak - in command \string\dirkeys; or no '=' sign}\@ehd + in command \string\dirkeys, or no '=' sign}\@ehd }% }% }% - \skvexpanded{\skvparselist*{\skv@keyparser}}\skv@tempa\skv@tempa{% - \expandafter\dirkeys@do\skv@tempa==\dirkeys@nil + \skvexpanded{\skvdolist*{\skv@keyparser}}\skv@tempa\skv@tempa{% + \expandafter\skv@dirkeys@split\skv@tempa==\dirkeys@nil }% - \indirkeysfalse - \skvpopstate\dirkeys@state\dirkeys@depth + \skvindirkeysfalse + \skvpopstate\skv@dirkeys@state\dirkeys@depth } \skvrobustdef*\dirkeys@setdefaultroot{% \ifx\dirkeys@familylist\@empty @@ -4659,7 +5257,7 @@ \fi \fi \ifx\dirkeys@prefixlist\@empty - \def\dirkeys@prefixlist{KV}% + \let\dirkeys@prefixlist\skv@defaultpref \fi \ifx\dirkeys@holderprefixtoks\@empty \def\dirkeys@holderprefixtoks{user@}% @@ -4692,8 +5290,7 @@ \begingroup % #1 may contain parameter characters that may be confused with % ##1 and ##2 below. Hence we put it in the macro \skv@tempb. - % Ignored keys are always defined. This saves resources and has - % so far been harmless. + % Note: Ignored keys are omitted by \skvdefinekeys. \edef\skv@tempb{\unexpanded{#1}}% \def\skv@tempa{}% \def\do##1##2{% @@ -4718,9 +5315,9 @@ #2\ifdirkeys@saveunknownkeys*\else\ifskv@handlerswa*\fi\fi [##1]{##2}[\skvcsuse{##1/##2/.@ignoredkeys}]% % #1 may contain unbalanced conditionals; hence the need for - % \skvifdefbool here. When setting 'rm keys', then no + % \skvifdefboolTF here. When setting 'rm keys', then no % key list is needed here. - \skvifdefbool{skv@handlerswb}{}{{\skvexpandonce\skv@tempb}}% + \skvifdefboolTF{skv@handlerswb}{}{{\skvexpandonce\skv@tempb}}% }% }% \dirkeys@getcurrentroots\do @@ -4736,9 +5333,9 @@ \def\do##1##2{% \def\skv@tempb{}% \skvletcs\skv@igkeys{##1/##2/.@ignoredkeys}% - \skvifdef\skv@igkeys{}{\def\skv@igkeys{}}% + \skvifdefTF\skv@igkeys{}{\def\skv@igkeys{}}% \skvcommaparse{#1}\skv@tempa{% - \skvxifin{,\skvoxdetok\skv@tempa,}{,\skvoxdetok\skv@igkeys,}{}{% + \skvxifinTF{,\skvoxdetok\skv@tempa,}{,\skvoxdetok\skv@igkeys,}{}{% \edef\skv@tempb{% \skvexpandonce\skv@tempb\ifx\skv@tempb\@empty\else,\fi \skvexpandonce\skv@tempa @@ -4747,7 +5344,7 @@ }% \edef\skv@tempd{% \skvexpandonce\skv@tempd - \skvifempty\skv@tempb{}{% + \skvifemptyTF\skv@tempb{}{% \noexpand#2[##1]{##2}{\skvexpandonce\skv@tempb}% }% }% @@ -4805,16 +5402,46 @@ \skv@prova#1#2\skv@novalue#2\skv@nil } +% Pushing and popping prefix, family or holder prefix. +% +\skvnewnumbers[dirkeys@meta]{prefixdepth,familydepth,hpdepth} +\skvrobustdef*\dirkeys@pushmeta#1{% + \skvifcase\skvifstrcmpTF{#1}% + {prefix}{\def\@elt{prefixlist}}% + {family}{\def\@elt{familylist}}% + {hp}{\def\@elt{holderprefixtoks}}% + \elsedo + \skv@err{Unknown meta type '#1'}\@ehd + \endif + \skvaftercs\skvgadvanceno{dirkeys@meta#1depth}\@ne + \edef\skv@elt{\skvrom\csname dirkeys@meta#1depth\endcsname}% + \skvcsletcs{dirkeys@\@elt @meta@\skv@elt}{dirkeys@\@elt}% +} +\skvrobustdef*\dirkeys@popmeta#1{% + \skvifcase\skvifstrcmpTF{#1}% + {prefix}{\def\@elt{prefixlist}}% + {family}{\def\@elt{familylist}}% + {hp}{\def\@elt{holderprefixtoks}}% + \elsedo + \skv@err{Unknown meta type '#1'}\@ehd + \endif + \edef\skv@elt{\skvrom\csname dirkeys@meta#1depth\endcsname}% + \skvcsletcs{dirkeys@\@elt}{dirkeys@\@elt @meta@\skv@elt}% + \skvaftercs\skvgadvanceno{dirkeys@meta#1depth}\m@ne +} + % Assigning admissible values to keys. The handlers here are: % -% .choice, .choice expanded, .choice expanded once, .choice expanded twice. +% .state pattern, .state pattern expanded, .state pattern expanded once, +% .state pattern expanded twice. % % \dirkeys@savechoice{<list>}{<expander.type>} % % 1. <list> has the form % -% <key1>/{<ch1>.do={<act1>},...,<ch-n>.do={<act-n>}},..., -% <key-n>/{<ch1>.do={<act1>},...,<ch-n>.do={<act-n>}} +% {<key1,...,keyn>}/{<ch1>.do={<act1>},...,<ch-n>.do={<act-n>}} +% ,..., +% <keyx-n>/{<ch1>.do={<act1>},...,<ch-n>.do={<act-n>}} % % 2. If it didn't exist, the main key (eg, the above <key1>) will be % defined with an empty default value and an empty callback. @@ -4835,30 +5462,32 @@ \skvkvnormalize\skvcurrentsub \def\skv@doonroot##1##2{% \skvletcs\skv@igkeys{##1/##2/.@ignoredkeys}% - \skvifdef\skv@igkeys{}{\def\skv@igkeys{}}% - \skvxifin{,\skvcurrentmaintoks,}{,\skv@igkeys,}{}{% - \skvifcsdef{##1/##2/\skvcurrentmaintoks.@cbk}{}{% - \edef\skv@tempd{% - \skvexpandonce\skv@tempd - \skvordkey[##1]{##2}{\skvcurrentmaintoks}[]{}% + \skvifdefTF\skv@igkeys{}{\def\skv@igkeys{}}% + \skvcommaparse*\skvcurrentmaintoks\skv@tempb{% + \skvxifinTF{,\skv@tempb,}{,\skv@igkeys,}{}{% + \skvifcsdefTF{##1/##2/\skv@tempb.@cbk}{}{% + \edef\skv@tempd{% + \skvexpandonce\skv@tempd + \skvordkey[##1]{##2}{\skv@tempb}[]{}% + }% }% - }% - \def\skv@choicelist{}% - \skvcommaloop*\skvcurrentsub\skv@tempa{% - \def\skv@prova####1.do=####2.do=####3\skv@nil{% - \edef\skv@choicelist{% - \skvexpandonce\skv@choicelist - {\skvtrimspace{####1}}{\skvtrimspace{####2}}% + \def\skv@choicelist{}% + \skvcommaloop*\skvcurrentsub\skv@tempa{% + \def\skv@prova####1.do=####2.do=####3\skv@nil{% + \edef\skv@choicelist{% + \skvexpandonce\skv@choicelist + {\skvtrimspace{####1}}{\skvtrimspace{####2}}% + }% }% + \expandafter\skv@prova\skv@tempa.do=.do=\skv@nil }% - \expandafter\skv@prova\skv@tempa.do=.do=\skv@nil }% - }% - \edef\skv@tempd{% - \skvexpandonce\skv@tempd - \skvappendkeycode[##1]{##2}{\skvcurrentmaintoks}% - {\dirkeys@executechoice{#2}{########1}% - {\skvexpandonce\skv@choicelist}}% + \edef\skv@tempd{% + \skvexpandonce\skv@tempd + \skvappendkeycode[##1]{##2}{\skv@tempb}% + {\dirkeys@executechoice{#2}{########1}% + {\skvexpandonce\skv@choicelist}}% + }% }% }% \skv@rootlist @@ -4870,10 +5499,10 @@ \skvdespacecontent\skv@prova \def\do##1##2##3\skv@nil{% \edef\skv@provb{\unexpanded{##1}}% - \skvifx\skv@provb\skv@prova{% + \skvifxTF\skv@provb\skv@prova{% ##2% }{% - \skvifblank{##3}{% + \skvifblankTF{##3}{% \skv@err{No choice match found for key '\skvcurrentkey'}\@ehd }{% \do##3\skv@nil @@ -4933,36 +5562,35 @@ \skvkvnormalize\skvcurrentsub \def\skv@doonroot##1##2{% \skvletcs\skv@igkeys{##1/##2/.@ignoredkeys}% - \skvifdef\skv@igkeys{}{\def\skv@igkeys{}}% + \skvifdefTF\skv@igkeys{}{\def\skv@igkeys{}}% \skvcommaloop*\skvcurrentmaintoks\skv@maintoks{% - \skvxifin{,\skv@maintoks,}{,\skv@igkeys,}{}{% - \skvifcsdef{##1/##2/\skv@maintoks.@cbk}{}{% + \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. \edef\skv@tempd{% \skvexpandonce\skv@tempd - \skvordkey[##1]{##2}{.value required{\skv@maintoks}}{}% + \skvordkey[##1]{##2}{.need value{\skv@maintoks}}{}% }% }% \def\skv@stylelist{}% \skvcommaloop*\skvcurrentsub\skv@tempa{% - \def\skv@prova####1=####2=####3\skv@nil{% - \skvxifstrcmp{\skv@maintoks}{####1}{% + \skv@kvosplit\skv@tempa{% + \skvxifstrcmpTF{\skv@maintoks}{####1}{% \skv@err{Linking key '####1' to itself}\@ehd }{% - \skvifcsdef{##1/##2/####1.@cbk}{}{% + \skvifcsdefTF{##1/##2/####1.@cbk}{}{% \skv@err{Style key '####1' is undefined}\@ehd }% }% - \skvxifin{,####1,}{,\skv@igkeys,}{}{% + \skvxifinTF{,####1,}{,\skv@igkeys,}{}{% \edef\skv@stylelist{% \skvaddlist,\skv@stylelist\unexpanded{####1}=% \skvexpandonce\skvexpander{\unexpanded{####2}}% }% }% }% - \expandafter\skv@prova\skv@tempa==\skv@nil }% }% \edef\skv@tempd{% @@ -4970,7 +5598,7 @@ % The styles contain value expanders \@firstofone, \unexpanded, etc. % They will be expanded by the next \skvexpanded when the main key % is set. - \skvifstrcmp{#2}{app}\skvappendkeycode\skvprependkeycode + \skvifstrcmpTF{#2}{app}\skvappendkeycode\skvprependkeycode [##1]{##2}{\skv@maintoks}% {\skvexpanded{\skvsetkeys[##1]{##2}% {\skvexpandonce\skv@stylelist}}}% @@ -5044,12 +5672,12 @@ \skvkvnormalize\skv@tempd \def\skv@doonroot##1##2{% \skvletcs\skv@igkeys{##1/##2/.@ignoredkeys}% - \skvifdef\skv@igkeys{}{\def\skv@igkeys{}}% + \skvifdefTF\skv@igkeys{}{\def\skv@igkeys{}}% \skvcommaloop*\skv@tempd\skv@tempa{% - \def\skv@prova####1=####2=####3\skv@nil{% - \skvxifin{,####1,}{,\skv@igkeys,}{}{% - \skvifcsdef{##1/##2/####1.@cbk}{% - \skvifblank{####2}{}{% + \skv@kvosplit\skv@tempa{% + \skvxifinTF{,####1,}{,\skv@igkeys,}{}{% + \skvifcsdefTF{##1/##2/####1.@cbk}{% + \skvifblankTF{####2}{}{% \edef\skv@tempe{% \skvexpandonce\skv@tempe\unexpanded{% \skvcsedef{##1/##2/####1.@#2arg}{\unexpanded{####2}}% @@ -5061,7 +5689,6 @@ }% }% }% - \expandafter\skv@prova\skv@tempa==\skv@nil }% }% \dirkeys@getcurrentroots\skv@doonroot @@ -5075,7 +5702,7 @@ \def\skv@defaultlist{}% \skvcommaparse{#3}\skvcurrentkey{% \skvletcs\skv@prova{#1/#2/\skvcurrentkey.@defa}% - \skvifdef\skv@prova{% + \skvifdefTF\skv@prova{% \skv@getdefault{#1}{#2}\skvcurrentkey\skvcurrentvalue \edef\skv@defaultlist{% \skvaddlist,\skv@defaultlist @@ -5095,13 +5722,13 @@ \begingroup \def\skv@tempa{}\def\skv@tempb{}% \def\do##1##2{% - \skvxifin{,##1,}{,\skv@tempa,}{}{% + \skvxifinTF{,##1,}{,\skv@tempa,}{}{% \edef\skv@tempa{% \skvexpandonce\skv@tempa \ifx\skv@tempa\@empty\else,\fi##1% }% }% - \skvxifin{,##2,}{,\skv@tempb,}{}{% + \skvxifinTF{,##2,}{,\skv@tempb,}{}{% \edef\skv@tempb{% \skvexpandonce\skv@tempb \ifx\skv@tempb\@empty\else,\fi##2% @@ -5117,7 +5744,7 @@ %%++++++++++++++++++++++++++ Try setting keys +++++++++++++++++++++++%% % % \skvtrysetkeys[<options>]{<keyvals>} -% .try set keys={<options>}{<keyvals>} +% .try set keys={<options>} % % Try to set a given key-value list on the paths given by the independent % options '.prefix/.prefixes' and '.family/.families' of \skvtrysetkeys. If @@ -5182,43 +5809,95 @@ % 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@]{% - .ords/{.try,.max attempt,.max attempts,.total}/12/ - \edef\skvtry@maxattempts{\number#1}% + .ord/{.try,.max attempt,.max attempts,.total}/12/ + \def\skvtry@maxattempts{#1}% + \skvstripouterbraces{2}\skvtry@maxattempts + \edef\skvtry@maxattempts{\number\skvtry@maxattempts}% \skvensureinteger{.max attempt}\skvtry@maxattempts - \ifnum#1<\@ne + \ifnum\skvtry@maxattempts<\@ne \skv@err{The max. number of attempts ('try') \MessageBreak can't be less than 1}\@ehd \fi , - .ords/{.upper goal,.max success,.max hits}/1/ - \edef\skvtry@maxsuccess{\number#1}% + .ord/{.upper goal,.max success,.max hits}/1/ + \def\skvtry@maxsuccess{#1}% + \skvstripouterbraces{2}\skvtry@maxsuccess + \edef\skvtry@maxsuccess{\number\skvtry@maxsuccess}% \skvensureinteger{upper goal}\skvtry@maxsuccess - \ifnum#1<\@ne + \ifnum\skvtry@maxsuccess<\@ne \skv@err{The max. number of successful attempts \MessageBreak ('upper goal') can't be less than 1}\@ehd \fi , - .ords/{.min success,.lower goal,.goal}/1/ - \edef\skvtry@minsuccess{\number#1}% + .ord/{.min success,.lower goal,.goal}/1/ + \def\skvtry@minsuccess{#1}% + \skvstripouterbraces{2}\skvtry@minsuccess + \edef\skvtry@minsuccess{\number\skvtry@minsuccess}% \skvensureinteger{lower goal}\skvtry@minsuccess - \ifnum#1<\@ne + \ifnum\skvtry@minsuccess<\@ne \skv@err{The min. number of successful attempts \MessageBreak ('lower goal') can't be less than 1}\@ehd \fi , - .ords/{.prefix,.prefixes,.add prefix,.add prefixes}/KV/ + .ord/{.prefix,.prefixes,.add prefix,.add prefixes}/\skv@defaultpref/ \edef\skvtry@prefs{#1} \skvstripouterbraces{2}\skvtry@prefs - \edef\skvtry@prefs{\skvifempty\skvtry@prefs{KV}{\skvtry@prefs}}% + \edef\skvtry@prefs{% + \skvifemptyTF\skvtry@prefs\skv@defaultpref\skvtry@prefs + }% \ifskv@insa \skvexpbracenext{\skvmergelist\skvtry@prefs}\dirkeys@prefixlist \fi \skvcsvnormalize\skvtry@prefs , - .ords/{.family,.families,.add family,.add families}/^skv^/ + .ord/{.family,.families,.add family,.add families}/\@nil/ \edef\skvtry@fams{#1} - \ifx\skvtry@fams\skv@rej\else + \skvstripouterbraces{2}\skvtry@fams + \ifx\skvtry@fams\@nnil\else \skvstripouterbraces{2}\skvtry@fams \ifskv@insa \skvexpbracenext{\skvmergelist\skvtry@fams}\dirkeys@familylist @@ -5226,26 +5905,30 @@ \skvcsvnormalize\skvtry@fams \fi , - .ords/{.path,.paths,.add path,.add paths,.root,.roots}/^skv^/ + .ord/{.path,.paths,.add path,.add paths,.root,.roots}/\@nil/ \edef\skv@tempa{\skvtrimspace{#1}} \skvstripouterbraces{2}\skv@tempa - \ifcase0\ifx\skv@tempa\skv@rej1\else + \ifcase0\ifx\skv@tempa\@nnil1\else \ifx\skv@tempa\@empty1\fi\fi\relax\skvafterfi - \skvexpbracenext\skvtry@fixpaths\skv@tempa + \skvexpbracenext\skvtry@processpaths\skv@tempa \fi , - .ords/{.ignore keys,.filter keys}// + .ord/{.ignore keys,.filter keys}// \def\skvtry@igkeys{#1} \skvstripouterbraces{2}\skvtry@igkeys , - .ords/{.save known keys,.save success}/true/ - \edef\skvtry@savesuccess{0\skvifstrcmp{#1}{true}01} + .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} , - .ords/{.save known keys in,.success list,.success list macro}/ - \skvsuccesslist/\def\skvtry@successlistmacro{#1} + .ord/{.save known keys in,.success list,.success list macro}/ + \skvsuccesslist/ + \def\skvtry@successlistmacro{#1} + \skvstripouterbraces{2}\skvtry@successlistmacro , } -\skvrobustdef*\skvtry@fixpaths#1{% +\skvrobustdef*\skvtry@processpaths#1{% \def\skvtry@prefs{}% \def\skvtry@fams{}% \def\skv@tempc##1/##2/##3\skv@nil{% @@ -5278,44 +5961,44 @@ \skvrobustdef*\skvtrysetkeys{\skv@testopt\skv@trysetkeys{}} \skvrobustdef*\skv@trysetkeys[#1]#2{% \skvpushfunctions\skvtrysetkeys{% - % Don't include \skvsuccesslist here! \do\skvtry@fams\do\skvtry@prefs\do\skvtry@maxattempts \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\skvcurrentprefix\do\skvcurrentfamily }\skv@trysetkeysdepth \skvsetkeys[SKV]{skvtryset}{#1}% \ifx\skvtry@fams\skv@rej \skv@err{No families in which to 'try' to set keys}\@ehd \fi \skv@getkeynames{#2}\skv@naa - \ifnum\skv@trysetkeysdepth=\@ne - \expandafter\def\skvtry@successlistmacro{}% - \def\skv@tempsuccesslist{}% - \fi + \expandafter\def\skvtry@successlistmacro{}% + \def\skv@tempsuccesslist{}% \skv@intrytrue \skvcommaparse{#2}\CurrentOption{% \expandafter\skv@g@tkeyname\CurrentOption=\skv@nil\skvcurrentkey - \skvxifin{,\skvcurrentkey,}{,\skvtry@igkeys,}{}{% + \skvxifinTF{,\skvcurrentkey,}{,\skvtry@igkeys,}{}{% + \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 \skv@successfalse - % Don't use \chardef here; it won't printed in the error message + % 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{% - \skvpushfunctions\skv@trysetkeys@istate{% - \do\CurrentOption\do\skvcurrentkey\do\skvcurrentprefix - \do\skvcurrentfamily\do\skv@attempts\do\skv@hits - \do\skv@breakprefloop\do\ifskv@success - }\skv@trysetkeysdepth@b \skvexpanded{% % Don't use \skv@setkeys@a here: \skv@fams, etc. % will be mixed up. \skvsetkeys[\skvcurrentprefix]{\skvcurrentfamily}% {\skvexpandonce\CurrentOption}% }% - \skvpopfunctions\skv@trysetkeys@istate\skv@trysetkeysdepth@b \edef\skv@attempts{\the\numexpr\skv@attempts+1}% \ifskv@success \edef\skv@hits{\the\numexpr\skv@hits+1}% @@ -5346,6 +6029,7 @@ \noexpand\skvtrysetkeys\fi. \MessageBreak Actual hits were '\skv@hits'}\@ehd \fi + \skvpopfunctions\skv@trysetkeys@istate\skv@trysetkeysdepth@b }% }% \expandafter\let\skvtry@successlistmacro\skv@tempsuccesslist @@ -5361,7 +6045,10 @@ %%+++++++++++++++++++++++++ 'search also' set keys +++++++++++++++++++%% % % \skvsasetkeys[<options>]{<keyvals>} -% .sa set keys={<options>}{<keyvals>} +% .sa set keys={<options>} +% +% When using '.sa set keys', the key '.key values' must be part of +% <options>. % % 1. The only difference between \skvsasetkeys and \skvtrysetkeys is that, % when in \directkeys, the values of the options <prefix/prefixes> and @@ -5373,11 +6060,11 @@ % 2. All the options of \skvtrysetkeys apply to \skvsasetkeys. \skvnewlet\skvsasetkeys\skvtrysetkeys -\skvrobustdef*\dirkeys@dosasetkeys#1{% +\skvrobustdef*\dirkeys@sasetkeys#1{% \skv@insatrue - \skvifundef\dirkeys@familylist{\def\dirkeys@familylist{}}{}% - \skvifundef\dirkeys@prefixlist{\def\dirkeys@prefixlist{}}{}% - \skv@trysetkeys[#1]% + \skvifdefTF\dirkeys@familylist{}{\def\dirkeys@familylist{}}% + \skvifdefTF\dirkeys@prefixlist{}{\def\dirkeys@prefixlist{}}% + \dirkeys@trysetkeys{#1}% } % \dirkeys@addorremoveroots{<list>}{<operator>} @@ -5386,21 +6073,38 @@ \skvcsvnormalize[/]\skv@prova \def\skv@tempa{}\def\skv@tempb{}% \skvcommaparse*\skv@prova\skv@prova{% - \def\skv@provb##1/##2/##3\skv@nil{% - \skvxifin{,##1,}{,\skv@tempa,}{}{% - \edef\skv@tempa{\skv@tempa\ifx\skv@tempa\@empty\else,\fi##1}% + \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}% }% - \skvxifin{,##2,}{,\skv@tempb,}{}{% - \edef\skv@tempb{\skv@tempb\ifx\skv@tempb\@empty\else,\fi##2}% + \skvxifinTF{,\skv@provb,}{,\skv@tempb,}{}{% + \edef\skv@tempb{\skv@tempb\ifx\skv@tempb\@empty\else,\fi\skv@provb}% }% }% - \expandafter\skv@provb\skv@prova//\skv@nil }% \skv@clfalse \skvexpbracenext{#2\dirkeys@prefixlist}\skv@tempa \skvexpbracenext{#2\dirkeys@familylist}\skv@tempb } - +\skvrobustdef*\skv@trimslashes#1{% + \begingroup + \skvxifinFT{\skvrelax/}{\skvrelax#1}{}{% + \def\do/##1\skv@nil{\def#1{##1}}% + \expandafter\do#1\skv@nil + }% + \skvxifinFT{/\skvrelax}{#1\skvrelax}{}{% + \def\do##1/\skv@nil{\def#1{##1}}% + \expandafter\do#1\skv@nil + }% + \skvaftergroupdef#1\endgroup +} % \dirkeys@addtocodeorvalue{app/pre}{cbk/value}{<list>} \skvrobustdef*\dirkeys@addtocodeorvalue#1#2#3{% @@ -5411,16 +6115,16 @@ % ##1=prefix, ##2=family \def\do##1##2{% \skvletcs\skv@igkeys{##1/##2/.@ignoredkeys}% - \skvifdef\skv@igkeys{}{\def\skv@igkeys{}}% + \skvifdefTF\skv@igkeys{}{\def\skv@igkeys{}}% \skvkvparse*\skv@tempa\skv@tempa{% \expandafter\skv@kvsplit\expandafter{\skv@tempa}{% - \skvxifin{,\detokenize{####1},}{,\skvoxdetok\skv@igkeys,}{}{% + \skvxifinTF{,\detokenize{####1},}{,\skvoxdetok\skv@igkeys,}{}{% \skvletcs\skv@prova{##1/##2/####1.@#2}% - \skvifundef\skv@prova{% + \skvifdefFT\skv@prova{% \skv@err{Key '####1' isn't in family '##1/##2'}\@ehd }{% \skvcsedef{##1/##2/####1.@#2}{% - \skvifstrcmp{#1}{pre}{% + \skvifstrcmpTF{#1}{pre}{% \skvtrimspace{####2}\skvexpandonce\skv@prova }{% \skvexpandonce\skv@prova\skvtrimspace{####2}% @@ -5449,11 +6153,11 @@ % ##1=prefix, ##2=family \def\do##1##2{% \skvletcs\skv@igkeys{##1/##2/.@ignoredkeys}% - \skvifdef\skv@igkeys{}{\def\skv@igkeys{}}% + \skvifdefTF\skv@igkeys{}{\def\skv@igkeys{}}% \skvkvparse*\skv@tempa\skv@tempa{% \expandafter\skv@kvsplit\expandafter{\skv@tempa}{% - \skvxifin{,\detokenize{####1},}{,\skvoxdetok\skv@igkeys,}{}{% - \skvifcsdef{##1/##2/####1.@cbk}{% + \skvxifinTF{,\detokenize{####1},}{,\skvoxdetok\skv@igkeys,}{}{% + \skvifcsdefTF{##1/##2/####1.@cbk}{% \skvcsedef{##1/##2/####1.@defa}{% \skvnoexpandcs{##1/##2/####1}{\skvtrimspace{####2}}% }% @@ -5482,11 +6186,11 @@ % ##1=prefix, ##2=family \def\do##1##2{% \skvletcs\skv@igkeys{##1/##2/.@ignoredkeys}% - \skvifdef\skv@igkeys{}{\def\skv@igkeys{}}% + \skvifdefTF\skv@igkeys{}{\def\skv@igkeys{}}% \skvkvparse*\skv@tempa\skv@tempa{% \expandafter\skv@kvsplit\expandafter{\skv@tempa}{% - \skvxifin{,\detokenize{####1},}{,\skvoxdetok\skv@igkeys,}{}{% - \skvifcsdef{##1/##2/####1.@cbk}{% + \skvxifinTF{,\detokenize{####1},}{,\skvoxdetok\skv@igkeys,}{}{% + \skvifcsdefTF{##1/##2/####1.@cbk}{% \skvcsedef{##1/##2/####1.@value}{\skvtrimspace{####2}}% \edef\skv@tempb{% \skvexpandonce\skv@tempb @@ -5503,19 +6207,19 @@ \skvexpanded{\endgroup\skv@tempb}% } -% \dirkeys@inherit{value/cbk/defa}{<list>} +% \dirkeys@inherit{value.or.cbk.or.defa}{<list>} \skvrobustdef*\dirkeys@inherit#1#2{% % Hid the list from the parameters of \do: \edef\skv@tempa{\unexpanded{#2}}% % ##1=prefix, ##2=family \def\do##1##2{% \skvletcs\skv@igkeys{##1/##2/.@ignoredkeys}% - \skvifdef\skv@igkeys{}{\def\skv@igkeys{}}% + \skvifdefTF\skv@igkeys{}{\def\skv@igkeys{}}% \skvkvparse*\skv@tempa\skv@tempa{% \expandafter\skv@slsplit\expandafter{\skv@tempa}{% - \skvxifin{,\detokenize{####1},}{,\skvoxdetok\skv@igkeys,}{}{% - \ifcase\skvifcsdef{##1/##2/####1.@cbk}{0}{1}% - \skvifcsdef{##1/##2/####2.@cbk}{0}{1}\relax + \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}% \else \skv@err{Key '####1' or '####2' isn't in family '##1/##2'}\@ehd @@ -5527,17 +6231,21 @@ \dirkeys@getcurrentroots\do } -% \dirkeys@setbooleanhandler{<handler>}{<boolean>}{<bool value>} +% \dirkeys@setbooleanhandler{<handler>}{<boolean>}{<bool.value>} \skvrobustdef*\dirkeys@setbooleanhandler#1#2#3{% - \skvifblank{#3}{% - \csname#2true\endcsname - }{% - \skvifboolval{#3}{% - \csname#2#3\endcsname + \skvifcsdefTF{if#2}{% + \skvifblankTF{#3}{% + \csname#2true\endcsname }{% - \skv@err{Invalid value '\detokenize{#3}' for handler '#1': - \MessageBreak its expects either 'true' or 'false'}\@ehd + \skvifboolvalTF{#3}{% + \csname#2#3\endcsname + }{% + \skv@err{Invalid value '\detokenize{#3}' for handler '#1': + \MessageBreak its expects either 'true' or 'false'}\@ehd + }% }% + }{% + \skv@err{No boolean '\detokenize{#2}'}\@ehd }% } @@ -5546,68 +6254,89 @@ \skv@err{A dot (.) must lead handler name '#1'}\@ehd \fi } -\skvrobustdef*\skv@handlerloop#1{% +\skvrobustdef*\dirkeys@handlerloop#1{% \edef\skv@tempa{\unexpanded{#1}}% \skvstripouterbraces{2}\skv@tempa \skvkvparse*\skv@tempa } -% \dirkeys@defhandlers{<marker>}{<list>} -% <marker> indicates if we're in <new> or <define> handler. +% \dirkeys@defhandlers{<flag>}{<list>} +% <flag> indicates if we're in <new> (01) or <define> (00) handler. \skvrobustdef*\dirkeys@defhandlers#1#2{% - \def\do##1=##2=##3\handler@nil{% - \skv@ensurehandlerdot{##1}% - \if0#1% - \skvcsdef{dirkeys@handler@##1}####1{##2}% - \else - \skvifcsdef{dirkeys@handler@##1}{% - \skv@err{Handler '##1' arealdy exists}\@ehd + \dirkeys@handlerloop{#2}\skv@tempa{% + \skv@kvosplit\skv@tempa{% + \skv@ensurehandlerdot{##1}% + \skvifplaswTF{#1}{% + \skvcsdef{dirkeys@handler@##1}####1{##2}% }{% - \skvcsdef{dirkeys@handler@##1}####1\handlereov{##2}% + \skvifcsdefTF{dirkeys@handler@##1}{% + \skv@err{Handler '##1' arealdy exists}\@ehd + }{% + \skvcsdef{dirkeys@handler@##1}####1\handlereov{##2}% + }% }% - \fi - }% - \skv@handlerloop{#2}\skv@tempa{% - \expandafter\do\skv@tempa==\handler@nil + }% }% } % Define handlers of more than one argument. This is slightly more % expensive than '.new handlers': -% \dirkeys@defnarghandlers{<marker>}{<list>} -% <marker> indicates if we're in <new> or <define> handler. +% \dirkeys@defnarghandlers{<flag>}{<list>} +% <flag> indicates if we're in <new> (01) or <define> (00) handler. \skvrobustdef*\dirkeys@defnarghandlers#1#2{% - \def\do##1=##2=##3\handler@nil{% - \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}% - }% - \if0#1% - \skv@provb - \else - \skvifcsdef{dirkeys@handler@##1}{% - \skv@err{Handler '##1' arealdy exists}\@ehd - }{% + \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 + }{% + \skvifcsdefTF{dirkeys@handler@##1}{% + \skv@err{Handler '##1' arealdy exists}\@ehd + }{% + \skv@provb + }% }% - \fi + }% + \skv@tempa##2\handler@nil }% - \skv@tempa##2\handler@nil }% - \skv@handlerloop{#2}\skv@tempa{% - \expandafter\do\skv@tempa==\handler@nil +} + +% \dirkeys@handlerlet{<flag>}{<kvlist>} +% <flag> is either 00 (for define) or 01 (for new 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 + }{% + \skvifblankTF{##1}{% + \skv@err{No child handler}\@ehd + }{% + \skvifplaswTF{#1}{}{% + \skvifcsdefFT{dirkeys@handler@##1}{}{% + \skv@err{Handler '##1' arealdy exists}\@ehd + }% + }% + \skvcsletcs{dirkeys@handler@##1}{dirkeys@handler@##2}% + }% + }% + }% }% } \skvrobustdef*\skvusehandler#1#2{% \skv@ensurehandlerdot{#1}% - \skvifcsdef{dirkeys@handler@#1}{% + \skvifcsdefTF{dirkeys@handler@#1}{% \csname dirkeys@handler@#1\endcsname#2\handlereov }{% \skv@err{Handler '#1' is undefined}\@ehd @@ -5624,19 +6353,18 @@ % 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{% - \dirkeys@defhandlers{1}{#1}% + \dirkeys@defhandlers{01}{#1}% } -% In case one gives no value to a handler: -\skvundef\dirkeys@ + \dirkeys*{% .new handlers={% .exec code=#1, - .define handlers=\dirkeys@defhandlers{0}{#1}, - .define narg handlers=\dirkeys@defnarghandlers{0}{#1}, - .new narg handlers=\dirkeys@defnarghandlers{1}{#1}, + .define handlers=\dirkeys@defhandlers{00}{#1}, + .define narg handlers=\dirkeys@defnarghandlers{00}{#1}, + .new narg handlers=\dirkeys@defnarghandlers{01}{#1}, .kill handlers={% - \skv@handlerloop{#1}\skv@tempa{% - \skvifcsdef{dirkeys@handler@\skv@tempa}{% + \dirkeys@handlerloop{#1}\skv@tempa{% + \skvifcsdefTF{dirkeys@handler@\skv@tempa}{% \skvcsundef{dirkeys@handler@\skv@tempa}% }{% \skv@err{Handler '\skv@tempa' is undefined}\@ehd @@ -5644,30 +6372,15 @@ }% }, .use handler=\skvusehandler{#1}, - .handler let={% - \def\do##1=##2=##3\handler@nil{% - \skvifcsdef{dirkeys@handler@##1}{% - \skv@err{Handler '##1' arealdy exists}\@ehd - }{% - \skvifcsundef{dirkeys@handler@##2}{% - \skv@err{Handler '##2' doesn't exist}\@ehd - }{% - \skvifblank{##1}{% - \skv@err{No child handler}\@ehd - }{% - \skvcsletcs{dirkeys@handler@##1}{dirkeys@handler@##2}% - }% - }% - }% - }% - \skv@handlerloop{#1}\skv@tempa{% - \expandafter\do\skv@tempa==\handler@nil - }% - }, + .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}% }, @@ -5715,8 +6428,8 @@ .pop prefixes=\dirkeys@popmeta{prefix}, .push families=\dirkeys@pushmeta{family}, .pop families=\dirkeys@popmeta{family}, - .push roots=\dirkeys@pushmeta{root}, - .pop roots=\dirkeys@popmeta{root}, + .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={% @@ -5724,8 +6437,8 @@ {.save unknown keys}{dirkeys@saveunknownkeys}{#1}% }, .save unknown keys in={% - \skvifblank{#1}{}{% - \skvifescaped{#1}{% + \skvifblankTF{#1}{}{% + \skvifescapedTF{#1}{% \dirkeys@saveunknownkeystrue \def\dirkeys@unknownkeysmacro{#1}% }{% @@ -5753,7 +6466,7 @@ \dirkeys@dosetkeys{#1}\skvsetkeys }, .set rmkeys={% - \skvifblank{#1}{% + \skvifblankTF{#1}{% \skv@handlerswafalse\skv@handlerswbtrue \dirkeys@dosetkeys{}\skvsetrmkeys }{% @@ -5764,7 +6477,7 @@ }% }, .set rmkeys*={% - \skvifblank{#1}{% + \skvifblankTF{#1}{% \skv@handlerswatrue\skv@handlerswbtrue \dirkeys@dosetkeys{}\skvsetrmkeys }{% @@ -5823,10 +6536,10 @@ % 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>}} - .choice=\dirkeys@savechoice{#1}{x0}, - .choice expand once=\dirkeys@savechoice{#1}{x1}, - .choice expand twice=\dirkeys@savechoice{#1}{x2}, - .choice expanded=\dirkeys@savechoice{#1}{xx}, + .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}, @@ -5898,7 +6611,7 @@ .no such key={4}{% % All the parameters would have been despaced when this handler % is called. #1=prefix, #2=family, #3=key, #4=value. - \skvifcsdef{#1@#2@handler}{% + \skvifcsdefTF{#1@#2@handler}{% \csname#1@#2@handler\endcsname{#1}{#2}{#3}{#4} }{% \skv@err{Key '#3' is not in family '#1/#2'}\@ehd @@ -5918,8 +6631,8 @@ }, % .get value={<pref>}{<fam>}{<key>}<cmd> .get value={4}{% - \skvifcsdef{#1/#2/#3.@value}{% - \skvifescaped{#4}{% + \skvifcsdefTF{#1/#2/#3.@value}{% + \skvifescapedTF{#4}{% \skvletcs#4{#1/#2/#3.@value}% }{% \skv@err{Token '\detokenize{#4}' isn't escaped}\@ehd @@ -5931,16 +6644,13 @@ }, % '.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. - % .try set keys={<options>}{<kvlist>} - .try set keys={2}{% - \skv@trysetkeys[{#1}]{#2} - }, + % 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>}{<kvlist>} - .sa set keys={2}{% - \dirkeys@dosasetkeys{#1}{#2} - }, + % .sa set keys={<options>} + .sa set keys={1}{\dirkeys@sasetkeys{#1}}, % .set boolean handler={<handler>}{<boolean>}{<value>} .set boolean handler={3}{% \dirkeys@setbooleanhandler{#1}{#2}{#3} @@ -5966,6 +6676,10 @@ .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, @@ -5982,7 +6696,11 @@ .try set=.try set keys, .sa set=.sa set keys, .search also set keys=.sa set keys, .use defaults=.set with defaults, - .echoice=.choice expanded, + .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, @@ -6012,11 +6730,11 @@ }, } -% \skvpatchcmd[<prefix>]{<cmd>}{<search>}{<replace>}{<succeed>}{<fail>} +% \skvpatchcmd[<prefix>]{<cmd>}{<search>}{<replace>}{<success>}{<fail>} \skvrobustdef*\skvpatchcmd{% \begingroup \@makeother{\#}\endlinechar\m@ne - \skv@testopt\skv@patchcmd{########1}% + \skv@testopt\skv@patchcmd{####1}% } \skvrobustdef*\skv@patchcmd[#1]#2#3#4{% \ifskv@tracingkeys @@ -6025,7 +6743,7 @@ \skv@p@tchcmd{#1}{#2}{#3}{#4}% } \skvrobustdef*\skv@p@tchcmd#1#2#3#4{% - \skvifpatchable{#2}{#3}{#4}{% + \skvifpatchableTF{#2}{#3}{#4}{% \skv@patchdebug{++}{Command is patchable}% \skv@patchdebug{==}{Patching has begun}% \begingroup @@ -6046,20 +6764,20 @@ }% } \skvrobustdef*\skv@patchdebug#1#2{% - \ifskv@tracingkeys\typeout{[debug] #1 #2}\fi + \ifskv@tracingkeys\typeout{[debug] #1 #2.}\fi } -\skvrobustdef*\skvifpatchable#1#2#3{% +\skvrobustdef*\skvifpatchableTF#1#2#3{% \endgroup - \skvifundef{#1}{% + \skvifdefFT{#1}{% \skv@patchdebug{--}{Command not defined}% \@secondoftwo }{% \skv@patchdebug{++}{Command is defined}% - \skvifmacro{#1}{% + \skvifmacroTF{#1}{% \skv@patchdebug{++}{Command is a macro}% - \skvifscannable{#1}{% + \skvifscannableTF{#1}{% \skv@patchdebug{++}{Macro can be retokenized safely after patching}% - \skvifpattern{#2}{#1}{% + \skvifpatternTF{#2}{#1}{% \skv@patchdebug{++}{Requested search pattern found}% \@firstoftwo }{% @@ -6096,7 +6814,7 @@ \catcode`\noexpand\}=\the\catcode`\}\relax }% } -\skvrobustdef*\skvifscannable#1{% +\skvrobustdef*\skvifscannableTF#1{% % Fails if the content of #1 is already detokenized. \begingroup \edef\skv@tempa##1{% @@ -6115,7 +6833,7 @@ \expandafter\@secondoftwo \fi } -\skvrobustdef\skvifpattern#1#2{% +\skvrobustdef\skvifpatternTF#1#2{% \begingroup \edef\skv@tempa##1{\def##1####1\detokenize{#1}####2\skvrelax}% \skv@tempa\skv@tempa{% @@ -6128,21 +6846,28 @@ \edef\skv@tempb##1{##1\detokenize{#1}\skvrelax}% \skv@tempb{\expandafter\skv@tempa\meaning#2}% } -\skvrobustdef*\skvifmacro#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 +\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@tempb##1{##1\detokenize{macro}:\skvrelax}% - \skv@tempb{\expandafter\skv@tempa\meaning#1}% } -%\skvxzapspaces{\detokenize{\begin{\document}}}\skv@begindoc@string -\edef\skv@begindoc@string{\string\begin\string{\string\document\string}} + +\skvrobustdef*\skvifmacroFT#1{\skvifmacroTF{#1}\@secondoftwo\@firstoftwo} + +%\skvxzapspaces{\detokenize{\begin{\document}}}\skv@begindoctoks +\edef\skv@begindoctoks{\string\begin\string{\string\document\string}} \skv@core@restorecodes \endinput |