summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/latex/skeyval/skeyval-for.tex
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/latex/skeyval/skeyval-for.tex')
-rw-r--r--Master/texmf-dist/tex/latex/skeyval/skeyval-for.tex687
1 files changed, 425 insertions, 262 deletions
diff --git a/Master/texmf-dist/tex/latex/skeyval/skeyval-for.tex b/Master/texmf-dist/tex/latex/skeyval/skeyval-for.tex
index b02ed4f91ed..309a5649c93 100644
--- a/Master/texmf-dist/tex/latex/skeyval/skeyval-for.tex
+++ b/Master/texmf-dist/tex/latex/skeyval/skeyval-for.tex
@@ -1,5 +1,5 @@
%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
-% This is file 'skeyval-for', version 1.1, October 2012. %
+% This is file 'skeyval-for', 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, %
@@ -26,25 +26,48 @@
% Copyright (c) 2010-2012 Ahmed Musa (amusa22@gmail.com). %
%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
+\begingroup%
+\let\e\endlinechar\edef\p{\the\e}\e13\edef\n{\the\catcode\e}%
+\xdef\skv@for@restorecatcodes{%
+ \let\noexpand\skv@for@restorecatcodes\relax%
+ \endlinechar=\p\relax\catcode\number\e=\n\relax%
+ \catcode\string`\noexpand`\string=\the\catcode\string``\relax%
+ \catcode\string`\noexpand=\string=\the\catcode\string`=\relax%
+}%
+\endgroup%
+\endlinechar\string=13\relax%
+\catcode13\string=5\relax%
+\catcode\string``\string=12\relax
+\catcode\string`=\string=12\relax
+\def\skvgobble#1{}
+\def\do#1{\catcode`\expandafter\skvgobble\string#1=\the\catcode`#1\relax}
+\edef\skv@for@restorecatcodes{%
+ \unexpanded\expandafter{\skv@for@restorecatcodes}%
+ \do\ \do\%\do\@\do\(\do\)\do\[\do\]\do\|\do\:\do\;\do\,\do\.%
+ \do\>\do\<\do\!\do\*\do\+\do\-\do\^\do\_\do\&\do\$\do\~\do\'%
+ \do\"\do\
+}
+\catcode`\ =10\relax
+\catcode`\@=11 \catcode`\(=12 \catcode`\)=12 \catcode`\[=12
+\catcode`\]=12 \catcode`\|=12 \catcode`\:=12 \catcode`\;=12
+\catcode`\,=12 \catcode`\*=12 \catcode`\+=12 \catcode`\-=12
+\catcode`\<=12 \catcode`\>=12 \catcode`\!=12 \catcode`\.=12
+\catcode`\^=07 \catcode`\_=08 \catcode`\&=04 \catcode`\$=03
+\catcode`\~=13 \catcode`\%=14 \catcode`\'=12 \catcode`\"=12
+
\csname skeyval-for-loaded\endcsname
\expandafter\let\csname skeyval-for-loaded\endcsname\endinput
-\edef\skv@for@restorecatcodes{%
- \catcode`\noexpand\@\the\catcode`\@\relax
- \let\noexpand\skv@for@restorecatcodes\relax
-}
-\catcode`\@=11\relax
-
\ifx\ProvidesFile\@undefined
- \message{File 'skeyval-for.tex' 2012/10/15 v1.1
+ \message{File 'skeyval-for.tex' 2012/10/16 v1.1a
Loops for skeyval package (AM)}
\else
\ProvidesFile{skeyval-for.tex}
- [2012/10/15 v1.1 Loops for skeyval package (AM)]
+ [2012/10/16 v1.1a Loops for skeyval package (AM)]
\@addtofilelist{skeyval-for.tex}
\fi
-\skvrobustdef*\skv@nostackerr{\skv@err{You've called empty stack}\@ehd}
+\skvrobustdef*\skv@nostackerr{\skv@err{You've called an empty stack}\@ehd}
% \skvsavestate<base-fn>{<fn-list>}<counter>
\skvrobustdef*\skvsavestate#1#2#3{%
\skvgadvanceno#3\@ne
@@ -52,7 +75,7 @@
\let\s\string\escapechar\m@ne
\def\skv@prova##1{\s##1@skv@\romannumeral#3}%
\def\do##1{\let\noexpand##1\skvnoexpandcs{\skv@prova{##1}}}%
- \skvifcsdef{\s#1@skv@stack}{}{\skvcsdef{\s#1@skv@stack}{\nostack}}%
+ \skvifcsdefTF{\s#1@skv@stack}{}{\skvcsdef{\s#1@skv@stack}{\nostack}}%
\skvcsxdef{\s#1@skv@stack}{#2{\skvexpandcsonce{\s#1@skv@stack}}}%
\def\do##1{\let\skvnoexpandcs{\skv@prova{##1}}\noexpand##1}%
\edef\reserved@a{\endgroup#2}\reserved@a
@@ -71,25 +94,27 @@
\skvgadvanceno#2\m@ne
}
-\skvnewregisters\bool{\ifskvbreakloop\ifforeachlastitem
- \ifskvprocessempty\ifskv@tempst\ifskv@foreach@swa
+\skvnewregisters\bool{%
+ \ifskvbreakloop\ifforeachlastitem
+ \ifskvprocessempty\ifskv@foreach@swa
\ifskv@foreach@swb\ifskv@foreach@parenth
}
\skvnewnumbers[skv@]{csvdepth,dolistcnt}
\skvrobustdef*\skv@usetempst#1#2{%
- \edef#2{\skvifdefbool{skv@tempst}\skvexpandonce\unexpanded{#1}}%
+ \edef#2{\skvifdefboolTF{skv@tempst}\skvexpandonce\unexpanded{#1}}%
}
%
% \skvdolist{<parser>}{<list>}<holdercmd>{<callback>}
% \skvdolist*{<parser>}{<listcmd>}<holdercmd>{<callback>}
%
-% 1. This can be nested to any depth, with different parsers on each
+% 1. \skvdolist can process both csv and tsv/nsv lists.
+% 2. This can be nested to any depth, with different parsers on each
% level.
-% 2. This will not process an empty list; see \skvecommaloop.
-% 3. For comma lists, \skvcommaloop and \skvcommaparse are faster.
+% 3. This will not process an empty list; see \skvecommaloop.
+% 4. For comma lists, \skvcommaloop and \skvcommaparse are faster.
% See later.
-% 4. For processing kv lists, use \skvkvparse.
+% 5. For processing kv lists, use \skvkvparse.
%
\skvrobustdef*\skvdolist{\skv@testst\skv@dolist}
\skvrobustdef*\skv@dolist#1#2#3#4{%
@@ -97,7 +122,7 @@
\skv@usetempst{#2}#3%
\def\skv@dolist@a{skv@dolist@\skvrom\skv@dolistcnt}%
\skvcsdef{\skv@dolist@a}##1##2##3#1{%
- \skvifstrcmp{##3}{\skv@dolist@nil}{%
+ \skvifstrcmpTF{##3}{\skv@dolist@nil}{%
% To allow nesting of loop:
\skvbreakloopfalse
}{%
@@ -111,7 +136,7 @@
\@nameuse{\skv@dolist@a}##1{##2}%
}%
}%
- \skvifempty#3{}{%
+ \skvifemptyTF#3{}{%
\edef\reserved@a{\unexpanded{\@nameuse{\skv@dolist@a}#3{#4}}}%
\expandafter\reserved@a#3#1\skv@dolist@nil#1%
}%
@@ -150,7 +175,7 @@
\let\skvreversedo\@iden
\skvrobustdef*\skv@removetrailingparser#1#2{%
- \skvxifin{\detokenize{#1}\relax}{\skvoxdetok#2\relax}{%
+ \skvxifinTF{\detokenize{#1}\relax}{\skvoxdetok#2\relax}{%
\def\skv@prova##1#1\skv@trim@nil{\unexpanded{##1}}%
\edef#2{\expandafter\skv@prova#2\skv@trim@nil}%
}{}%
@@ -175,10 +200,18 @@
% \ifnum\@tempcnta<4
% \fi
%
+\skvnewcounts{skv@recurse@cnt}
\skvrobustdef\skvrecurse#1\while#2\fi{%
+ \skv@recurse@cnt\skvz@
\@expandtwoargs\skv@dobody{\skvtrimspace{#2}}{\skvtrimspace{#1}}%
}
\skvrobustdef\skv@dobody#1#2{%
+ \advance\skv@recurse@cnt\@ne
+ \ifnum\skv@recurse@cnt>10000\relax
+ \@latex@error{Possibly an infinite loop in \string\skvrecurse}
+ {Maybe you didn't increment some counter or
+ \MessageBreak the termination condition was never satisfied.}%
+ \fi
#1\relax\expandafter\@iden\else\expandafter\@gobble\fi
{#2\relax\skv@dobody{#1}{#2}}%
}
@@ -186,8 +219,8 @@
% A version of LaTeX's \@tfor that can parse undoubled parameter
% characters.
%
-% \skvtfor<holder.cmd>{<list>}\do{<callback>}
-% \skvtfor*<holder.cmd>{<listcmd>}\do{<callback>}
+% \skvtfor<holder.cmd>:={<list>}\do{<callback>}
+% \skvtfor*<holder.cmd>:={<listcmd>}\do{<callback>}
%
% Example:
%
@@ -206,15 +239,15 @@
\skvrobustdef*\skv@tfor#1:={\skv@tf@r#1 }
\skvrobustdef\skv@tf@r#1#2\do#3{%
\edef#1{\skvtrimspace{#2}}%
- \edef#1{\skvifbool{skv@tempst}\skvexpandtwice\skvexpandonce{#1}}%
- \skvifempty#1{}{%
+ \edef#1{\skvifboolTF{skv@tempst}\skvexpandtwice\skvexpandonce{#1}}%
+ \skvifemptyTF#1{}{%
\skvbreakloopfalse
\expandafter\skv@tforloop#1\skv@tfor@nil\skv@tfor#1{#3}%
}%
}
\skvrobustdef\skv@tforloop#1#2\skv@tfor#3#4{%
\edef#3{\unexpanded{#1}}%
- \skvifx#3\skv@tfor@nil{%
+ \skvifxTF#3\skv@tfor@nil{%
\skvbreakloopfalse
}{%
#4\relax
@@ -230,7 +263,7 @@
}%
}
-% Non-expandable comma loops
+%+++++++++++++++ Non-expandable comma loops ++++++++++++++%%
%
% 1. These follow from \skvdolist and \skvparselist, but they are
% specialized for comma lists and they are faster.
@@ -245,12 +278,12 @@
\skv@usetempst{#1}#2%
% Don't put \skvcsvnormalize#2 here. Use \skvcommaparse instead.
% Some callers of \skvcommaloop already have their lists normalized.
- \skvifx#2\@empty{}{%
+ \skvifxTF#2\@empty{}{%
\skvexpandnext{\skv@c@mmaloop#2{#3}}#2,\skv@commaloop@nil,%
}%
}
\skvrobustdef\skv@c@mmaloop#1#2#3,{%
- \skvifstrcmp{#3}{\skv@commaloop@nil}{%
+ \skvifstrcmpTF{#3}{\skv@commaloop@nil}{%
\skvbreakloopfalse
}{%
\edef#1{\unexpanded{#3}}%
@@ -289,7 +322,6 @@
\skvcsvnormalize#2%
\skvcommaloop*#2#2{#3}%
}
-%
% \skvkvparse{<list>}<cmd>{<callback>}
% \skvkvparse*{<listcmd>}<cmd>{<callback>}
%
@@ -303,12 +335,59 @@
\skvkvnormalize#2%
\skvcommaloop*#2#2{#3}%
}
+% \skvcommaprocess{<list>}<holder.cmd>
+% \skvcommaprocess*{<listcmd>}<holder.cmd>
+%
+% If <list> or <listcmd> is a single item, then no looping is required.
%
+\skvrobustdef*\skvcommaprocess{\skv@testst\skv@commaprocess}
+\skvrobustdef*\skv@commaprocess#1#2#3{%
+ \skv@usetempst{#1}#2%
+ \skvxifinTF{,}{\skvoxdetok#2}{%
+ \skvcommaparse*#2#2{#3}%
+ }{%
+ \skvdespacecontent#2#3%
+ }%
+}
+% \skvcountelements[<parser>]{<list>}{<return.cmd>}
+% \skvcountelements*[<parser>]{<listcmd>}{<return.cmd>}
+\skvrobustdef*\skvcountelements{\skv@teststopt\skv@countelements,}
+\skvrobustdef*\skv@countelements[#1]#2#3{%
+ \begingroup
+ \skv@usetempst{#2}\skv@tempa
+ \@tempcnta\skvz@
+ \skvdolist*{#1}\skv@tempa\skv@prova{%
+ \advance\@tempcnta\@ne
+ }%
+ \edef#3{\the\@tempcnta}%
+ \skvaftergroupdef#3\endgroup
+}
+% If the number of elements in a list is equal or greater than <nr>.
+% \skvifelementcount[<parser>]{<list>}{<nr>}{<true>}{<false>}
+% \skvifelementcount*[<parser>]{<listcmd>}{<nr>}{<true>}{<false>}
+\skvrobustdef*\skvifelementcount{\skv@teststopt\skv@ifelementcount,}
+\skvrobustdef*\skv@ifelementcount[#1]#2#3{%
+ \begingroup
+ \skv@usetempst{#2}\skv@tempa
+ \@tempcnta\skvz@
+ \skv@swafalse
+ \skvdolist*{#1}\skv@tempa\skv@prova{%
+ \advance\@tempcnta\@ne
+ \ifnum\@tempcnta=#3\relax
+ \skv@swatrue\skvbreakloop
+ \fi
+ }%
+ \expandafter\endgroup\ifskv@swa
+ \expandafter\@firstoftwo
+ \else
+ \expandafter\@secondoftwo
+ \fi
+}
% \skv@foreach@normalize[<parser>]<listcmd>
\skvrobustdef*\skv@foreach@normalize{\skv@testopt\skv@foreach@norm@lize,}
\skvrobustdef*\skv@foreach@norm@lize[#1]#2{%
- \skvxifntype{\detokenize{#1}}\skvcsvnormalize\skvmacnormalize[#1]#2%
+ \skvxifntypeTF{\detokenize{#1}}\skvcsvnormalize\skvmacnormalize[#1]#2%
}
% \newforeach[<options>] <holders> {<list>} {<callback>}
@@ -332,7 +411,7 @@
\skvnewnumbers{foreachdepth,skv@foreach@sisterdepth,skv@foreach@nra,%
skv@warnsubparser}
\skvnewdef*\skv@foreach@onlyinitially{}
-\skvrobustdef*\skv@foreach@assignonce#1{%
+\skvrobustdef*\skvforeachonlyinitially#1{%
\edef\skv@foreach@onlyinitially{%
\skvexpandonce\skv@foreach@onlyinitially
\unexpanded{#1}%
@@ -341,7 +420,7 @@
% \skv@foreach@addtocallback{<pre.or.post>}{<code.to.add>}
\skvrobustdef*\skv@foreach@addtocallback#1#2{%
\skvcsedef{skv@foreach@#1callback}{%
- \skvifcsundef{skv@foreach@#1callback}{}{%
+ \skvifcsdefFT{skv@foreach@#1callback}{}{%
\skvexpandcsonce{skv@foreach@#1callback}%
}%
% No \unexpanded for #2 here, since #2 is to be expanded:
@@ -352,11 +431,11 @@
\skvnewlet\skv@foreach@codemark\relax
\skvrobustdef*\skv@foreach@addtohook#1#2#3{%
\begingroup
- \skvifdef#2{}{\def#2{}}%
+ \skvifdefTF#2{}{\def#2{}}%
\edef\x{\detokenize{\skv@foreach@codemark#3\skv@foreach@codemark}}%
- \skvxifin\x{\skvoxdetok#2}{}{%
+ \skvxifinTF\x{\skvoxdetok#2}{}{%
\edef#2{%
- \skvifstrcmp{#1}{pre}{%
+ \skvifstrcmpTF{#1}{pre}{%
\skv@foreach@codemark\unexpanded{#3}\skv@foreach@codemark
\skvexpandonce{#2}%
}{%
@@ -378,7 +457,7 @@
}
\skvnewlet\atbeginforeach\appendtobeginforeach
\skvrobustdef*\skv@atbeginforeach#1[#2]#3{%
- \skvifblank{#2}{%
+ \skvifblankTF{#2}{%
\skvaftercsname{\skv@foreach@addtohook{#1}}%
{skv@foreach@atbeginhook@\skvrom\@ne}{#3}%
}{%
@@ -398,7 +477,7 @@
}
\skvnewlet\atendforeach\appendtoendforeach
\skvrobustdef*\skv@atendforeach#1[#2]#3{%
- \skvifblank{#2}{%
+ \skvifblankTF{#2}{%
\skvaftercsname{\skv@foreach@addtohook{#1}}%
{skv@foreach@atendhook@\skvrom\@ne}{#3}%
}{%
@@ -437,8 +516,8 @@
\next
}
\skvrobustdef*\skv@foreach@ifholderisonecmd#1#2#3{%
- \skvifntype{#2}{%
- \skvifescaped{#2}{%
+ \skvifntypeTF{#2}{%
+ \skvifescapedTF{#2}{%
#3%
}{%
\skv@err{Value of key '#1' must
@@ -453,9 +532,9 @@
}
% \skv@foreach@maketester{<cond>}<cond.tester.cmd>{<flag>}
%
-% 1. Only balanced conditionals beginning with \if...\fi are allowed.
-% Restricting the type of allowed conditionals is necessary for
-% auto syntax checking.
+% 1. Only balanced conditionals beginning with \if... and ending with \fi
+% are allowed. Restricting the type of allowed conditionals is
+% necessary for auto syntax checking.
% 2. <flag> is either 0 or 1, signifying whether or not the condition
% should be entered in postcallback.
%
@@ -466,23 +545,23 @@
% characters. \skv@prova will appear only in the error message.
\begingroup
\edef\skv@prova{\detokenize{#1}}%
- \skvifblank{#1}{%
+ \skvifblankTF{#1}{%
\skv@err{A blank conditional given in \string\newforeach}\@ehd
}{%
- \skvxifin{\skv@foreach@fi\relax}{\detokenize{#1}\relax}{%
- \skvxifin{\relax\skv@foreach@if}{\relax\detokenize{#1}}{%
- \edef#2{\noexpand\skvifcondition\unexpanded{#1}}%
+ \skvxifinTF{\skv@foreach@fi\relax}{\detokenize{#1}\relax}{%
+ \skvxifinTF{\relax\skv@foreach@if}{\relax\detokenize{#1}}{%
+ \edef#2{\noexpand\skvifconditionTF\unexpanded{#1}}%
\ifnum#3=\@ne
\skv@foreach@addtocallback{post}{%
- \unexpanded{\skvifcondition#1}{\noexpand\skvbreakloop}{\relax}%
+ \unexpanded{\skvifconditionTF#1}{\noexpand\skvbreakloop}{}%
}%
\fi
}{%
- \skv@err{Illegal conditional '\skv@prova'}
+ \skv@err{Invalid conditional '\skv@prova'}
{Invalid, possibly unbalanced, conditional '\skv@prova'}%
}%
}{%
- \skv@err{Illegal conditional '\skv@prova'}\@ehd
+ \skv@err{Invalid conditional '\skv@prova'}\@ehd
}%
}%
\skvexpanded{\endgroup
@@ -517,7 +596,7 @@
}
}
-\quickkeys.define{skvforeach}{%
+\quickkeys.define{skeyval/foreach}{%
.exec/
\def\skv@foreach@parser{,}
\def\skv@foreach@subparser{/}
@@ -526,7 +605,7 @@
\ifskvindef\else
\edef\skv@foreach@parser{\unexpanded{#1}}
\skvstripouterbraces{2}\skv@foreach@parser
- \skvxifntype{\detokenize{#1}}{%
+ \skvxifntypeTF{\detokenize{#1}}{%
\begingroup
% It is assumed that every n-type parser and subparser
% must have catcode 12:
@@ -540,7 +619,7 @@
\ifskvindef\else
\edef\skv@foreach@subparser{\unexpanded{#1}}
\skvstripouterbraces{2}\skv@foreach@subparser
- \skvxifntype{\detokenize{#1}}{
+ \skvxifntypeTF{\detokenize{#1}}{
\begingroup
\skvexpandnext{\catcode`}\skv@foreach@subparser=12\relax
\skv@rescan\skv@foreach@subparser
@@ -552,10 +631,6 @@
\edef\skv@foreach@terminator{\unexpanded{#1}}%
\skvstripouterbraces{2}\skv@foreach@terminator
;
- list is a macro,macro list/true/
- \edef\skv@foreach@listismacro{0\skvifstrcmp{true}{#1}01}%
- /true,false
- ;
% process up to = <nr>
% Maximum number of items to process:
process up to,process up to number/\@nil/
@@ -567,7 +642,7 @@
\fi
;
process empty list/true/
- \edef\skv@foreach@processempty{0\skvifstrcmp{true}{#1}01}%
+ \edef\skv@foreach@processempty{0\skvifstrcmpTF{true}{#1}01}%
/true,false
;
% Eg, exit when=\ifnum\x=20\fi
@@ -626,7 +701,7 @@
% count in = \y all \x satisfying <condition> initially <value>
% Eg,
% count in = \p all \x satisfying \ifnum\x>4\fi, or
- % count in = \p all \x satisfying \skvifnum\x>4
+ % count in = \p all \x satisfying \skvifnumTF\x>4
% The counting is not additive, meaning that the counter is initialized
% to zero on each depth.
count in,count/\@nil/
@@ -655,7 +730,7 @@
\ifx\skv@prova\@nnil
\skv@err{Invalid empty value for key 'item counter'}\@ehd
\else
- \skvifescaped{#1}{%
+ \skvifescapedTF{#1}{%
\let\skv@foreach@itemcounter\skv@prova
}{%
\skv@err{Non-escaped value '\detokenize{#1}'
@@ -687,11 +762,11 @@
% Remember outside the loop the holder values. Of course, this
% means remembering only the latest values.
recover holder values,recover holder values after loop/true/
- \edef\skv@foreach@recoverholders{0\skvifstrcmp{true}{#1}01}%
+ \edef\skv@foreach@recoverholders{0\skvifstrcmpTF{true}{#1}01}%
/true,false
;
% This default value of 'link' is required by \skv@foreach@filllist:
- .exec/\def\skv@foreach@link{\@nil};
+ .exec code/\def\skv@foreach@link{\@nil};
link/\@nil/
\ifskvindef\else
\edef\skv@foreach@link{\unexpanded{#1}}%
@@ -709,7 +784,7 @@
\skv@err{Value required for key 'grow'}\@ehd
\else
\skvcsedef{skv@foreach@grow#1}{00}
- \edef\skv@prova{\skvifstrcmp{#1}{left}{right}{left}}%
+ \edef\skv@prova{\skvifstrcmpTF{#1}{left}{right}{left}}%
\skvcsedef{skv@foreach@grow\skv@prova}{01}%
\fi
\fi
@@ -721,37 +796,59 @@
;
grow left/true/
\ifskvindef\else
- \edef\skv@foreach@growleft{0\skvifstrcmp{true}{#1}01}
- \edef\skv@foreach@growright{0\skvifstrcmp{true}{#1}10}
+ \edef\skv@foreach@growleft{0\skvifstrcmpTF{true}{#1}01}
+ \edef\skv@foreach@growright{0\skvifstrcmpTF{true}{#1}10}
\fi
/true,false
;
grow right/true/
\ifskvindef\else
- \edef\skv@foreach@growright{0\skvifstrcmp{true}{#1}01}
- \edef\skv@foreach@growleft{0\skvifstrcmp{true}{#1}10}
+ \edef\skv@foreach@growright{0\skvifstrcmpTF{true}{#1}01}
+ \edef\skv@foreach@growleft{0\skvifstrcmpTF{true}{#1}10}
\fi
/true,false
;
% Keep the decimals in rounded numbers or dimensions when list is
% auto-completed. The value value of this key is 'true'.
keep decimals/true/
- \edef\skv@foreach@keepdecimals{0\skvifstrcmp{true}{#1}01}
+ \edef\skv@foreach@keepdecimals{0\skvifstrcmpTF{true}{#1}01}
/true,false
;
keep high decimals,keep only high decimals/true/
- \edef\skv@foreach@keephighdecimals{0\skvifstrcmp{true}{#1}01}
+ \edef\skv@foreach@keephighdecimals{0\skvifstrcmpTF{true}{#1}01}
/true,false
;
% This key means that, eg, for \x/\y, do \let\y=\x if \y has no
% user value, ie, if the user gives as an item 'a' instead of
% 'a/b' or 'a/a'.
- inherit/true/
- \edef\skv@foreach@inherit{0\skvifstrcmp{true}{#1}01}
+ inherit,transfer macro values/true/
+ \edef\skv@foreach@inherit{0\skvifstrcmpTF{true}{#1}01}
/true,false
;
- expand before fill/true/
- \edef\skv@foreach@expandbeforefill{0\skvifstrcmp{true}{#1}01}
+ expand before fill,expand list before fill/true/
+ \edef\skv@foreach@expandlistbeforefill{0\skvifstrcmpTF{true}{#1}01}
+ /true,false
+ ;
+ expand list once,*,list is a macro,macro list/true/
+ \edef\skv@foreach@expandlistonce{0\skvifstrcmpTF{true}{#1}01}%
+ /true,false
+ ;
+ expand list twice/true/
+ \edef\skv@foreach@expandlisttwice{0\skvifstrcmpTF{true}{#1}01}%
+ /true,false
+ ;
+ % Don't use 'expand' for this key, to avoid confusing it with
+ % the 'expand' for holder macros:
+ expand list,fully expand list,expand list fully/true/
+ \edef\skv@foreach@expandlistfully{0\skvifstrcmpTF{true}{#1}01}%
+ /true,false
+ ;
+ reverse list,reverse,reflect/true/
+ \edef\skv@foreach@reverselist{0\skvifstrcmpTF{true}{#1}01}
+ /true,false
+ ;
+ reverse list,reverse,reflect/true/
+ \edef\skv@foreach@reverselist{0\skvifstrcmpTF{true}{#1}01}
/true,false
;
}
@@ -762,11 +859,10 @@
% evaluate dim,*evaluate dim,expand,*expand,count in,*count in,
% loop stopper,process up to,grow
%
-\skvinitializeqkeys{skvforeach}{%
+\skvinitializeqkeys{skeyval/foreach}{%
parser,
subparser,
callback terminator,
- list is a macro=false,
process up to,
process empty list=false,
item counter,
@@ -779,24 +875,28 @@
keep high decimals=false,
inherit=false,
expand before fill=false,
+ reverse list=false,
+ expand list once=false,
+ expand list twice=false,
+ expand list fully=false,
}
\skvnewdef*\skv@foreach@kvlist{}
% \setupforeach{<kvlist>}
\skvrobustdef*\setupforeach#1{%
- \skvifblank{#1}{}{%
+ \skvifblankTF{#1}{}{%
\skvaddtolist\skv@foreach@kvlist{#1}%
}%
}
\skvrobustdef*\skv@foreach@setkeys#1{%
- \def\reserved@a{\quickkeys.set{skvforeach}}%
+ \def\reserved@a{\quickkeys.set{skeyval/foreach}}%
\expandafter\reserved@a\expandafter{\skv@foreach@kvlist,#1}%
}
% evaluate=<holder.macro> as <child.macro> using <formula>
%
% 1. Evaluation is done with \edef unless \pgfmathparse is present
-% in <formula>.
+% in <formula> or key 'pgf evaluate' is called.
%
% 2. <formula> must be a valid formula, eg,
%
@@ -817,7 +917,7 @@
\skvrobustdef*\skv@foreach@parseevaluate#1{%
\begingroup
\def\skv@tempxifin##1##2{%
- \skvxifin{\detokenize{##1}}{\detokenize{##2}}%
+ \skvxifinTF{\detokenize{##1}}{\detokenize{##2}}%
}%
\skv@foreach@swafalse
\def\skv@tempd{}%
@@ -828,8 +928,8 @@
\ifx\skv@prova\@empty
\skv@err{Value of key 'evaluate' has no holder macro}\@ehd
\else
- \expandafter\skvifescaped\expandafter{\skv@prova}{%
- \expandafter\skvifntype\expandafter{\skv@prova}{}{%
+ \expandafter\skvifescapedTF\expandafter{\skv@prova}{%
+ \expandafter\skvifntypeTF\expandafter{\skv@prova}{}{%
\skv@err{Value of key 'evaluate': more than 1
\MessageBreak token \skvoxdetok\skv@prova.
\MessageBreak I can't find holder macro}\@ehd
@@ -842,8 +942,8 @@
\ifx\skv@provb\@empty
\skv@err{Value of key 'evaluate' has no child macro}\@ehd
\else
- \expandafter\skvifescaped\expandafter{\skv@provb}{%
- \expandafter\skvifntype\expandafter{\skv@provb}{}{%
+ \expandafter\skvifescapedTF\expandafter{\skv@provb}{%
+ \expandafter\skvifntypeTF\expandafter{\skv@provb}{}{%
\skv@err{Value of key 'evaluate': more than 1
\MessageBreak token \skvoxdetok\skv@provb.
\MessageBreak I can't find child macro}\@ehd
@@ -910,7 +1010,7 @@
\ifx\@nnil#1\@nnil
\skv@err{Value of key 'evaluate' has no holder macro}\@ehd
\else
- \skvifntype{#1}{%
+ \skvifntypeTF{#1}{%
% Expand the holder macro:
\skv@tempa#1as#1using#1\skv@nil
}{%
@@ -950,7 +1050,7 @@
\skv@err{No \string\pgfmathparse; 'pgfmath' module not loaded}\@ehd
\fi
\def\skv@tempxifin##1##2{%
- \skvxifin{\detokenize{##1}}{\detokenize{##2}}%
+ \skvxifinTF{\detokenize{##1}}{\detokenize{##2}}%
}%
\skv@foreach@swafalse
\def\skv@tempa##1as##2using##3\skv@nil{%
@@ -960,8 +1060,8 @@
\ifx\skv@prova\@empty
\skv@err{Value of key 'pgfmath parse' has no holder macro}\@ehd
\else
- \expandafter\skvifescaped\expandafter{\skv@prova}{%
- \expandafter\skvifntype\expandafter{\skv@prova}{}{%
+ \expandafter\skvifescapedTF\expandafter{\skv@prova}{%
+ \expandafter\skvifntypeTF\expandafter{\skv@prova}{}{%
\skv@err{Value of key 'pgfmath parse': more than 1
\MessageBreak token \skvoxdetok\skv@prova.
\MessageBreak I can't find holder macro}\@ehd
@@ -974,8 +1074,8 @@
\ifx\skv@provb\@empty
\skv@err{Value of key 'pgfmath parse' has no child macro}\@ehd
\else
- \expandafter\skvifescaped\expandafter{\skv@provb}{%
- \expandafter\skvifntype\expandafter{\skv@provb}{}{%
+ \expandafter\skvifescapedTF\expandafter{\skv@provb}{%
+ \expandafter\skvifntypeTF\expandafter{\skv@provb}{}{%
\skv@err{Value of key 'pgfmath parse': more than 1
\MessageBreak token \skvoxdetok\skv@provb.
\MessageBreak I can't find child macro}\@ehd
@@ -1041,7 +1141,7 @@
\ifx\@nnil#1\@nnil
\skv@err{Value of key 'pgfmath parse' has no holder macro}\@ehd
\else
- \skvifntype{#1}{%
+ \skvifntypeTF{#1}{%
% Evaluate the holder macro:
\skv@tempa#1as#1using#1\skv@nil
}{%
@@ -1089,7 +1189,7 @@
\skvrobustdef*\skv@foreach@parsecountin#1{%
\begingroup
\def\skv@tempxifin##1##2{%
- \skvxifin{\detokenize{##1}}{\detokenize{##2}}%
+ \skvxifinTF{\detokenize{##1}}{\detokenize{##2}}%
}%
\def\skv@tempa##1\skv@nil{%
\skv@tempxifin{initially}{##1}{%
@@ -1106,8 +1206,8 @@
\ifx\skv@prova\@empty
\skv@err{Value of key 'count' has no counter macro}\@ehd
\else
- \expandafter\skvifescaped\expandafter{\skv@prova}{%
- \expandafter\skvifntype\expandafter{\skv@prova}{}{%
+ \expandafter\skvifescapedTF\expandafter{\skv@prova}{%
+ \expandafter\skvifntypeTF\expandafter{\skv@prova}{}{%
\skv@err{Value of key 'count in': more than 1
\MessageBreak token \skvoxdetok\skv@prova.
\MessageBreak I can't find counter macro}\@ehd
@@ -1120,7 +1220,7 @@
\ifx\skv@provd\@empty
\expandafter\def\skv@prova{0}%
\else
- \skvifinteger\skv@provd{%
+ \skvifintegerTF\skv@provd{%
\expandafter\let\skv@prova\skv@provd
}{%
\skv@err{Value of key 'count':\MessageBreak
@@ -1136,8 +1236,8 @@
\ifx\skv@provb\@empty\else
% If there isn't a holder macro or quantity to test, then no
% test is possible:
- \expandafter\skvifescaped\expandafter{\skv@provb}{%
- \expandafter\skvifntype\expandafter{\skv@provb}{}{%
+ \expandafter\skvifescapedTF\expandafter{\skv@provb}{%
+ \expandafter\skvifntypeTF\expandafter{\skv@provb}{}{%
\skv@err{Value of key 'count in': more than 1
\MessageBreak token \skvoxdetok\skv@provb.
\MessageBreak I can't find holder macro}\@ehd
@@ -1169,7 +1269,7 @@
\ifx\@nnil#1\@nnil
\skv@err{Value of key 'count' has no counter macro}\@ehd
\else
- \skvifntype{#1}{%
+ \skvifntypeTF{#1}{%
\skv@tempa#1all satisfying\skv@nil
}{%
\skv@err{Value of key 'count in': more than 1
@@ -1203,7 +1303,7 @@
\skvrobustdef*\skv@foreach@parseremember#1{%
\begingroup
\def\skv@tempxifin##1##2{%
- \skvxifin{\detokenize{##1}}{\detokenize{##2}}%
+ \skvxifinTF{\detokenize{##1}}{\detokenize{##2}}%
}%
\skv@tempxifin{(}{#1}{%
\skv@err{Value of key 'remember': '(' found.
@@ -1219,7 +1319,7 @@
\skv@err{Value of key 'remember' has no holder macro:
\MessageBreak i.e., no macro that holds input}\@ehd
\else
- \expandafter\skvifescaped\expandafter{\skv@prova}{}{%
+ \expandafter\skvifescapedTF\expandafter{\skv@prova}{}{%
\skv@err{Value of key 'remember':
\MessageBreak Holder macro \skvoxdetok\skv@prova not escaped}\@ehd
}%
@@ -1228,7 +1328,7 @@
\skv@err{Value of key 'remember' has no child macro;
\MessageBreak i.e., no macro after 'as'}\@ehd
\else
- \expandafter\skvifescaped\expandafter{\skv@provb}{%
+ \expandafter\skvifescapedTF\expandafter{\skv@provb}{%
\skv@foreach@swatrue
}{%
\skv@err{Value of key 'remember':
@@ -1286,7 +1386,7 @@
\skvrobustdef*\skv@foreach@parserecall#1{%
\begingroup
\def\skv@tempxifin##1##2{%
- \skvxifin{\detokenize{##1}}{\detokenize{##2}}%
+ \skvxifinTF{\detokenize{##1}}{\detokenize{##2}}%
}%
\skv@tempxifin{(}{#1}{%
\skv@err{Value of key 'recall': '(' found.
@@ -1301,8 +1401,8 @@
\skv@err{Value of key 'recall' has no holder macro:
\MessageBreak i.e., no macro that holds input}\@ehd
\else
- \expandafter\skvifntype\expandafter{\skv@prova}{%
- \expandafter\skvifescaped\expandafter{\skv@prova}{%
+ \expandafter\skvifntypeTF\expandafter{\skv@prova}{%
+ \expandafter\skvifescapedTF\expandafter{\skv@prova}{%
\edef\skv@elt{\expandafter\skvremovescape\skv@prova}%
\skv@foreach@swatrue
% Initially:
@@ -1349,6 +1449,23 @@
\fi
}%
}
+% \skv@foreach@doreverselist{<parser>}{<listcmd>}
+\skvnewdef*\skv@foreach@doreverselist#1#2{%
+ \begingroup
+ \def\skv@tempb{}%
+ \def\skv@tempa##1#1##2\skv@reverse@stop{%
+ \if\relax\detokenize{##2}\relax\skv@reverse@stop\fi
+ \skv@tempa##2\skv@reverse@stop
+ \edef\skv@tempb{%
+ \skvexpandonce\skv@tempb\ifx\skv@tempb\@empty\else#1\fi
+ \unexpanded{##1}%
+ }%
+ }%
+ \def\skv@reverse@stop##1\skv@reverse@stop{\fi}%
+ \expandafter\skv@tempa#2#1\skv@reverse@stop
+ \let#2\skv@tempb
+ \skvaftergroupdef#2\endgroup
+}
% Eg, \skv@dots@in<value>\skv@nil...\skv@nnil\skv@stop
\skvnewdef*\skv@dots@in#1...#2#3\skv@stop{%
@@ -1376,8 +1493,9 @@
\skvrobustdef*\skv@foreach@pushstate{%
\skvsavestate\skv@foreach@stack{%
+ \do\skv@foreach@seenstar
\do\skv@foreach@parser\do\skv@foreach@subparser
- \do\skv@foreach@listismacro
+ \do\skv@foreach@listisamacro
\do\skv@foreach@processupto\do\skv@foreach@processempty
\do\skv@foreach@exittester
\do\skv@foreach@grow\do\skv@foreach@growleft
@@ -1392,20 +1510,24 @@
\do\foreachlistremainder\do\skv@foreach@mainloop
\do\skv@foreach@getnext\do\skv@foreach@getrm
\do\skv@foreach@do@a\do\skv@foreach@do@b
+ \do\skv@foreach@paramlist
\do\skv@foreach@holderlist
\do\skv@foreach@userlist
\do\skv@foreach@inherit
\do\skv@foreach@keepdecimals
\do\skv@foreach@keephighdecimals
\do\skv@foreach@itemcounter
- \do\skv@foreach@link\do\skv@foreach@expandbeforefill
+ \do\skv@foreach@link
+ \do\skv@foreach@expandlistbeforefill\do\skv@foreach@expandlistonce
+ \do\skv@foreach@expandlisttwice\do\skv@foreach@expandlistfully
\do\skv@listbreakertoks\do\skv@listpausertoks
+ \do\skv@foreach@reverselist
\do\foreachcurrentitem
\do\foreachnextitem
\do\foreachitemcount
\do\foreachprevitem
% The following commands are disabled on entry into the loop.
- % Hence they need to be stacked:
+ % Hence they need to be stacked here:
\do\prependtobeginforeach
\do\appendtobeginforeach
\do\atbeginforeach
@@ -1422,14 +1544,15 @@
\skvnewdef*\skv@foreach@nnil{\skv@foreach@nil}
\skvrobustdef*\newforeach{\skv@testst\skv@newforeach@beginprescan}
\skvrobustdef*\skv@newforeach@beginprescan{%
- \edef\skv@foreach@st{0\ifskv@tempst0\else1\fi}%
+ \edef\skv@foreach@seenstar{0\ifskv@tempst0\else1\fi}%
\begingroup
+ \def\skv@foreach@holderlist{}%
\def\skv@tempa{%
\skvexpanded{\endgroup
- \noexpand\skv@foreach@endprescan{\skvexpandonce\skv@tempb}%
+ \noexpand\skv@foreach@endprescan
+ {\skvexpandonce\skv@foreach@holderlist}%
}%
}%
- \def\skv@tempb{}%
\let\bgroup\relax
\skvifnextchar[{%
\endgroup
@@ -1449,8 +1572,8 @@
}%
}
\skvrobustdef*\skv@foreach@collectholders#1{%
- \edef\skv@tempb{%
- \skvexpandonce\skv@tempb\skvtrimspace{#1}%
+ \edef\skv@foreach@holderlist{%
+ \skvexpandonce\skv@foreach@holderlist\skvtrimspace{#1}%
}%
\skvifnextchar[{%
\skv@tempa
@@ -1467,14 +1590,14 @@
}%
}
\skvrobustdef*\skv@foreach@endprescan#1[#2]{%
- \skvifblank{#1}{%
+ \skvifblankTF{#1}{%
\skv@err{\string\newforeach: no holder macros seen}\@ehd
}{%
\skv@foreach@scanarg[#2]#1%
}%
}
-\skvrobustdef*\skv@foreach@scanarg{\skv@testopt\skv@foreach@a{}}
-\skvrobustdef*\skv@foreach@a[#1]{%
+\skvrobustdef*\skv@foreach@scanarg{\skv@testopt\skv@foreach@scanarg@a{}}
+\skvrobustdef*\skv@foreach@scanarg@a[#1]{%
\skv@foreach@pushstate
\skv@foreach@latehookerr
% \foreachitemcount must be a macro, not a counter, because it is stacked:
@@ -1492,39 +1615,50 @@
% Since \skv@foreach@precallback are initialized in each nest, the
% keys have to be reset here.
\skv@foreach@setkeys{#1}%
+ % We've set the keys; let's overrule \skv@foreach@expandlistonce if
+ % we had seen a star suffix. Don't overrule \skv@foreach@expandlisttwice
+ % and \skv@foreach@expandlistfully.
+ \if\skv@foreach@seenstar
+ \def\skv@foreach@expandlistonce{00}%
+ \fi
+ \ifcase0%
+ \if\skv@foreach@expandlistonce0\else
+ \if\skv@foreach@expandlisttwice0\else
+ \if\skv@foreach@expandlistfully0\else 1\fi\fi\fi\relax
+ \def\skv@foreach@listisamacro{00}%
+ \else
+ \def\skv@foreach@listisamacro{01}%
+ \fi
\begingroup
% Collect item holders. Don't confuse explicit \bgroup for left brace:
\skv@cnta\skvz@
- \def\skv@tempb{}%
+ \def\skv@foreach@holderlist{}%
\let\bgroup\relax
- \skvifnextchar i\skv@foreach@c{%
- \skvifnextchar\skv@orig@bgroup\skv@foreach@d\skv@foreach@b
+ \skvifnextchar i\skv@foreach@scanarg@c{%
+ \skvifnextchar\skv@orig@bgroup
+ \skv@foreach@scanarg@d\skv@foreach@scanarg@b
}%
}
% #1: one holer macro or subparser.
-\skvrobustdef*\skv@foreach@b#1{%
- \ifnum\skv@cnta=\skvz@
- \skvifescaped{#1}{}{%
- \skv@err{Token '\noexpand#1' is not escaped
- \MessageBreak and can't be a holder macro}\@ehd
- }%
- \else
+\skvrobustdef*\skv@foreach@scanarg@b#1{%
+ % Odd items must be subparser:
+ \ifodd\skv@cnta
\ifnum\skv@cnta=\@ne
- \skvifescaped{#1}{%
+ \skvifescapedTF{#1}{%
\skv@err{Token '\noexpand#1' cannot be a subparser;
- \MessageBreak it seems to be a holder macro.
- \MessageBreak I expected the subparser to be the
- \MessageBreak second token here.}\@ehd
+ \MessageBreak it seems to be a holder macro. I expected
+ \MessageBreak the subparser to be the token here.}\@ehd
}{%
\edef\skv@prova{\skvtrimspace{#1}}%
\let\elt\skvexpandonce
- \def\skv@elt{\elt\skv@foreach@subparser}%
- \if\elt\skv@prova\skv@elt\else
- % Don't stack \skv@warnsubparser:
+ \let\skv@elt\skv@foreach@subparser
+ \if\elt\skv@prova\elt\skv@elt\else
+ % Don't stack \skv@warnsubparser, so that the following
+ % warning isn't called more than once in the inner loop.
\ifnum\skv@warnsubparser=\skvz@
\skvgadvanceno\skv@warnsubparser\@ne
\skv@warn{Scanned subparser '\elt\skv@prova' is different from
- \MessageBreak the default or user-supplied subparser '\skv@elt'.
+ \MessageBreak the default or user-supplied subparser '\elt\skv@elt'.
\MessageBreak I have used '\elt\skv@prova', but please submit
\MessageBreak '\elt\skv@prova' as the value of the key
'subparser'
@@ -1534,83 +1668,92 @@
\fi
}%
\fi
+ \else
+ \skvifescapedTF{#1}{}{%
+ \skv@err{Token '\noexpand#1' is not escaped
+ \MessageBreak and can't be a holder macro}\@ehd
+ }%
\fi
\advance\skv@cnta\@ne
- \edef\skv@tempb{\skvexpandonce\skv@tempb\skvtrimspace{#1}}%
- \skvifnextchar i\skv@foreach@c{%
- \skvifnextchar\skv@orig@bgroup\skv@foreach@d\skv@foreach@b
+ \edef\skv@foreach@holderlist{%
+ \skvexpandonce\skv@foreach@holderlist\skvtrimspace{#1}%
+ }%
+ \skvifnextchar i\skv@foreach@scanarg@c{%
+ \skvifnextchar\skv@orig@bgroup
+ \skv@foreach@scanarg@d\skv@foreach@scanarg@b
}%
}
-\skvrobustdef*\skv@foreach@c#1#2{%
- \skvifstrcmp{#1#2}{in}{%
- \skv@foreach@d
+\skvrobustdef*\skv@foreach@scanarg@c#1#2{%
+ \skvifstrcmpTF{#1#2}{in}{%
+ \skv@foreach@scanarg@d
}{%
\skv@err{I have seen 'i' but no expected 'in'}\@ehd
}%
}
-\skvrobustdef*\skv@foreach@d{%
- \ifx\skv@tempb\@empty
+\skvrobustdef*\skv@foreach@scanarg@d{%
+ \ifx\skv@foreach@holderlist\@empty
\skv@err{No item holder macros before 'in'
\MessageBreak or before left brace}\@ehd
\fi
\skvifnextchar\skv@orig@bgroup{%
- \skv@foreach@e
+ \skv@foreach@scanarg@e
}{%
- \if\skv@foreach@listismacro
- \expandafter\skv@foreach@e
+ \if\skv@foreach@listisamacro
+ \expandafter\skv@foreach@scanarg@e
\else
- \if\skv@foreach@st
- \expandafter\expandafter\expandafter\skv@foreach@e
- \else
- \def\reserved@a##1{%
- \skvifmacro{##1}{%
- \def\skv@ehd{Maybe a star (*) suffix or key 'list is
- a macro' is missing.}%
- }{%
- \let\skv@ehd\@ehd
- }%
- \skv@err{I expected a left brace for beginning of list,
- \MessageBreak since you haven't told me that your
- \MessageBreak list is a macro. Instead I found '\detokenize{##1}'.
- \MessageBreak If your list is indeed a macro, you can
- \MessageBreak either put star (*) after \noexpand\newforeach
- \MessageBreak or use the key 'list is a macro'%
- }{%
- \skv@ehd
- }%
+ \def\reserved@a##1{%
+ \skvifmacroTF{##1}{%
+ \def\skv@tempehd{Maybe a star (*) suffix after
+ \noexpand\newforeach or key 'expand list once', etc.,
+ \MessageBreak is missing.}%
+ }{%
+ \let\skv@tempehd\@ehd
}%
- \expandafter\expandafter\expandafter\reserved@a
- \fi
+ \skv@err{I expected a left brace for beginning of list,
+ \MessageBreak since you haven't told me that your
+ \MessageBreak list is a macro. Instead I found '\detokenize{##1}'.
+ \MessageBreak If your list is indeed a macro, you can
+ \MessageBreak either put star (*) after \noexpand\newforeach
+ \MessageBreak or use the key 'expand list once'
+ \MessageBreak or 'expand list twice' or 'list is a macro', etc.%
+ }\skv@tempehd
+ }%
+ \expandafter\reserved@a
\fi
}%
}
% #1: <list> or <listcmd>
-\skvrobustdef*\skv@foreach@e#1{%
- \edef\skv@tempc{\unexpanded{#1}}%
- \skvifnextchar\skv@orig@bgroup\skv@foreach@h{%
- \skvifnextchar d\skv@foreach@f\skv@foreach@g
+\skvrobustdef*\skv@foreach@scanarg@e#1{%
+ \edef\skv@foreach@userlist{\unexpanded{#1}}%
+ \skvifnextchar\skv@orig@bgroup\skv@foreach@scanarg@h{%
+ \skvifnextchar d\skv@foreach@scanarg@f\skv@foreach@scanarg@g
}%
}
-\skvrobustdef*\skv@foreach@f#1#2{%
- \skvifstrcmp{#1#2}{do}{%
- \skvifnextchar\skv@orig@bgroup\skv@foreach@h\skv@foreach@g
+\skvrobustdef*\skv@foreach@scanarg@f#1#2{%
+ \skvifstrcmpTF{#1#2}{do}{%
+ \skvifnextchar\skv@orig@bgroup
+ \skv@foreach@scanarg@h\skv@foreach@scanarg@g
}{%
\skv@err{I have seen 'd' but no the expected 'do'}\@ehd
}%
}
% We've exhausted all options for grabbing the callback, so now
-% look for terminator (default ;). If there is no terminator ahead,
-% the use of \skv@prova will trigger 'the use of ... does not match
-% its definition' or 'runaway argument ...'.
-\skvrobustdef*\skv@foreach@g{%
+% look for terminator (default ;).
+%
+% 1. If there is no terminator ahead, the use of \skv@prova will trigger
+% 'the use of ... does not match its definition' or
+% 'runaway argument ...'.
+% 2. This covers the case when \newforeach or \foreach comes next in
+% the callback.
+\skvrobustdef*\skv@foreach@scanarg@g{%
\def\skv@prova##1{%
\def\skv@prova####1##1{%
% Look out for a case like 'parser=<parser>'.
% Eg, \newforeach[parser=;]. In this case, the value ';' of
% key 'parser' will mistakenly be assumed to be the callback
% terminator. It should be enclosed in braces.
- \skvxifin{\detokenize{parser=}\relax}{\detokenize{####1}\relax}{%
- \skvxifin{[}{\detokenize{####1}}{%
+ \skvxifinTF{\detokenize{parser=}\relax}{\detokenize{####1}\relax}{%
+ \skvxifinTF{[}{\detokenize{####1}}{%
\skv@err{Put '##1' in braces for key 'parser=##1'.
\MessageBreak Try [parser={##1}]}
{Maybe parser '##1' is the value of a key/option of
@@ -1619,48 +1762,58 @@
one ending a TikZ object. Maybe you need to do [parser={##1}].}%
}{%
% Otherwise, let's try continue:
- \skvexpanded{\noexpand\skv@foreach@h{\skvtrimspace{####1}##1}}%
+ \skvexpanded{%
+ \noexpand\skv@foreach@scanarg@h{\skvtrimspace{####1}##1}%
+ }%
}%
}{%
- \skvexpanded{\noexpand\skv@foreach@h{\skvtrimspace{####1}##1}}%
+ \skvexpanded{%
+ \noexpand\skv@foreach@scanarg@h{\skvtrimspace{####1}##1}%
+ }%
}%
}%
\skv@prova
}%
- % In case callback terminator is currently active:
+ % In case callback terminator is currently active, rescan it.
\skv@rescan\skv@foreach@terminator
\expandafter\skv@prova\expandafter{\skv@foreach@terminator}%
}
% #1: callback
-\skvrobustdef*\skv@foreach@h#1{%
+\skvrobustdef*\skv@foreach@scanarg@h#1{%
\skvexpanded{\endgroup
- % The subparser may have changed along the way (see \skv@foreach@b):
+ % The subparser may have changed along the way
+ % (see \skv@foreach@scanarg@b):
\skvcmdexit\skv@foreach@subparser
- \skv@foreach@i{\skvexpandonce\skv@tempb}{\skvexpandonce\skv@tempc}%
+ \skv@foreach@mainprocess
+ {\skvexpandonce\skv@foreach@holderlist}%
+ {\skvexpandonce\skv@foreach@userlist}%
}{#1}%
}
% #1: holder macros
% #2: List or list command
% #3: Callback
-\skvrobustdef*\skv@foreach@i#1#2#3{%
- \if\skv@foreach@st\else
- \if\skv@foreach@listismacro
- \def\skv@foreach@st{00}%
- \else
- \def\skv@foreach@st{01}%
- \fi
- \fi
+\skvrobustdef*\skv@foreach@mainprocess#1#2#3{%
\edef\skv@foreach@userlist{%
- \if\skv@foreach@st
+ \if\skv@foreach@expandlistonce
\expandafter\skvexpandonce
\else
- \expandafter\unexpanded
+ \if\skv@foreach@expandlisttwice
+ \expandafter\expandafter\expandafter\skvexpandtwice
+ \else
+ \if\skv@foreach@expandlistfully
+ \expandafter\expandafter\expandafter\expandafter
+ \expandafter\expandafter\expandafter\@iden
+ \else
+ \expandafter\expandafter\expandafter\expandafter
+ \expandafter\expandafter\expandafter\unexpanded
+ \fi
+ \fi
\fi
{#2}%
}%
% Initial code, if any:
\skvcsuse{skv@foreach@atbeginhook@\skvrom\foreachdepth}%
- \skvifdef\foreachprevitem{}{\def\foreachprevitem{}}%
+ \skvifdefTF\foreachprevitem{}{\def\foreachprevitem{}}%
\expandafter\skv@foreach@normalize\expandafter
[\skv@foreach@parser]\skv@foreach@userlist
\expandafter\skv@foreach@normalize\expandafter
@@ -1694,21 +1847,21 @@
}%
\def\skv@foreach@do@a####1##1####2\skv@foreach@stop{%
\edef\foreachcurrentitem{\skvexpandonce{\@gobble####1}}%
- \skvifx\foreachcurrentitem\skv@foreach@nnil{%
+ \skvifxTF\foreachcurrentitem\skv@foreach@nnil{%
\skvbreakloopfalse
\foreachlastitemfalse
}{%
- \skvifx\foreachcurrentitem\skv@listbreakertoks{%
+ \skvifxTF\foreachcurrentitem\skv@listbreakertoks{%
\skv@foreach@getrm{####2}%
}{%
- \skvifx\foreachcurrentitem\skv@listpausertoks{%
+ \skvifxTF\foreachcurrentitem\skv@listpausertoks{%
\message{^^J! List pause:
^^JType x or X to quit, or <RETURN> to proceed^^J}%
\begingroup
\endlinechar\m@ne\global\read-1 to\@gtempa
\endgroup
\skvexpandarg\lowercase{\def\noexpand\@gtempa{\@gtempa}}%
- \skvxifstrcmp\@gtempa{x}{%
+ \skvxifstrcmpTF\@gtempa{x}{%
\skv@foreach@getrm{####2}%
}{%
\skv@foreach@do@b{####2}%
@@ -1721,26 +1874,26 @@
}%
\def\skv@foreach@do@b####1{%
\edef\foreachitemcount{\the\numexpr\foreachitemcount+1}%
- \ifnum0=\numexpr
- \ifx\skv@foreach@itemcounter\@undefined-1\else+0\fi
- \ifx\skv@foreach@itemcounter\@empty-1\else+0\fi
- \ifx\skv@foreach@itemcounter\@nnil-1\else+0\fi\relax\relax
+ \ifcase0%
+ \ifx\skv@foreach@itemcounter\@undefined 1\fi
+ \ifx\skv@foreach@itemcounter\@empty 1\fi
+ \ifx\skv@foreach@itemcounter\@nnil 1\fi\relax
\expandafter\let\skv@foreach@itemcounter\foreachitemcount
\fi
\skv@foreach@lookahead@a\skv@foreach@getnext####1\skv@foreach@stop
% In case the user decides to continue after \listpauser:
- \skvifx\foreachcurrentitem\skv@listpausertoks{}{%
+ \skvifxTF\foreachcurrentitem\skv@listpausertoks{}{%
\expandafter\skv@foreach@callback\expandafter{\foreachcurrentitem}%
}%
\let\foreachprevitem\foreachcurrentitem
- \ifx\skv@foreach@processupto\@undefined\else
- \ifx\skv@foreach@processupto\@nnil\else
- \ifnum\foreachitemcount<\skv@foreach@processupto\relax\else
- \skvbreakloop
- \fi
+ \ifcase0%
+ \ifx\skv@foreach@processupto\@undefined 1\fi
+ \ifx\skv@foreach@processupto\@nnil 1\fi\relax
+ \ifnum\foreachitemcount<\skv@foreach@processupto\relax\else
+ \skvbreakloop
\fi
\fi
- \skvifdefbool{skvbreakloop}{%
+ \skvifdefboolTF{skvbreakloop}{%
\skv@foreach@getrm{####1}%
}{%
\skv@foreach@lookahead@a\skv@foreach@do@a####1\skv@foreach@stop
@@ -1755,11 +1908,15 @@
}%
\skv@prova####1%
}%
- \skvifx\skv@foreach@userlist\@empty{%
+ \skvifxTF\skv@foreach@userlist\@empty{%
\if\skv@foreach@processempty\skv@foreach@callback{}\fi
}{%
\expandafter\skv@foreach@filllist\expandafter
{\skv@foreach@parser}\skv@foreach@userlist
+ \if\skv@foreach@reverselist\skvafterfi
+ \expandafter\skv@foreach@doreverselist\expandafter
+ {\skv@foreach@parser}\skv@foreach@userlist
+ \fi
\expandafter\skv@foreach@lookahead@a\expandafter\skv@foreach@do@a
\skv@foreach@userlist##1\skv@foreach@nil##1\skv@foreach@stop
}%
@@ -1776,6 +1933,9 @@
\skvrestorestate\skv@foreach@holderstate\skv@foreach@sisterdepth
\fi
\skv@foreach@popstate
+ \ifnum\foreachdepth=\skvz@
+ \def\skv@warnsubparser{0}%
+ \fi
}
% \skv@foreach@makeprecode{<holder.list>}
@@ -1850,12 +2010,11 @@
\skvcmdexit\skv@foreach@precallback
}%
}
-
% #1: callback
\skvrobustdef*\skv@foreach@makeauxcallback#1{%
\begingroup
\def\skv@generatesubparser##1{%
- \ifnum##1<10\skvexpandonce\skv@foreach@subparser
+ \ifnum##1<10 \skvexpandonce\skv@foreach@subparser
\expandafter\skv@generatesubparser
\expandafter{\number\numexpr##1+1\expandafter}%
\fi
@@ -1863,24 +2022,25 @@
% Add extra subparsers in case some items aren't subparser-complete:
\edef\skv@tempa{\skv@generatesubparser{1}}%
\let\foreacheov\relax
+ \let\\\noexpand
\skvexpanded{\endgroup
% Define auxiliary callback:
- \def\noexpand\skv@foreach@auxcallback\skv@foreach@paramlist\foreacheov{%
+ \def\\\skv@foreach@auxcallback\skv@foreach@paramlist\foreacheov{%
% Holder macro assignments:
\skvexpandonce\skv@foreach@precallback
% User tests/tasks, eg, if requested from 'evaluate' key:
\skvexpandonce\skv@foreach@afterprecallback
- \noexpand\ifnum\noexpand\foreachitemcount=\@ne
- \noexpand\skv@foreach@onlyinitially
- \noexpand\fi
+ \\\ifnum\\\foreachitemcount=\@ne
+ \\\skv@foreach@onlyinitially
+ \\\fi
\unexpanded{#1}%
% User tests/tasks, eg, if requested from the keys 'remember',
% 'exit when', etc:
\skvexpandonce\skv@foreach@postcallback
}%
% Define the real callback:
- \def\noexpand\skv@foreach@callback####1{%
- \noexpand\skv@foreach@auxcallback####1\skv@tempa\foreacheov
+ \def\\\skv@foreach@callback####1{%
+ \\\skv@foreach@auxcallback####1\skvxonce\skv@tempa\foreacheov
}%
}%
}
@@ -1917,12 +2077,12 @@
}
\skvnewdef*\skv@foreach@ifloweralpha#1{%
- \skvifblank{#1}{%
+ \skvifblankTF{#1}{%
\@secondoftwo
}{%
- \skvifntype{#1}{%
- \skvifnum`#1>96{%
- \skvifnum`#1<123{%
+ \skvifntypeTF{#1}{%
+ \skvifnumTF`#1>96{%
+ \skvifnumTF`#1<123{%
\@firstoftwo
}{%
\@secondoftwo
@@ -1936,12 +2096,12 @@
}%
}
\skvnewdef*\skv@foreach@ifupperalpha#1{%
- \skvifblank{#1}{%
+ \skvifblankTF{#1}{%
\@secondoftwo
}{%
- \skvifntype{#1}{%
- \skvifnum`#1>64{%
- \skvifnum`#1<91{%
+ \skvifntypeTF{#1}{%
+ \skvifnumTF`#1>64{%
+ \skvifnumTF`#1<91{%
\@firstoftwo
}{%
\@secondoftwo
@@ -1965,12 +2125,12 @@
\def\skv@foreach@origunit{}%
\def\skv@foreach@filledlist{}%
\edef\skv@foreach@parser{\skvtrimspace{#1}}%
- \ifx\skv@foreach@parser\@undefined
+ \ifx\skv@foreach@parser\@empty
\def\skv@foreach@parser{,}%
\fi
\def\skv@foreach@iflinkgiven{%
- \skvifdef\skv@foreach@link{%
- \skvnotifx\skv@foreach@link\@nnil
+ \skvifdefTF\skv@foreach@link{%
+ \skvifxFT\skv@foreach@link\@nnil
}{%
\skv@err{List auto-completion: 'link' is undefined}\@ehd
}%
@@ -1987,8 +2147,8 @@
\edef\skv@tempa{\unexpanded{#2}}%
\skv@foreach@normalize[#1]\skv@tempa
\def\skv@prova##1{%
- \skvxifin{...}{\detokenize{##1}}{%
- \if\skv@foreach@expandbeforefill
+ \skvxifinTF{...}{\detokenize{##1}}{%
+ \if\skv@foreach@expandlistbeforefill
\edef\skv@tempa{##1}%
\skv@foreach@normalize[#1]\skv@tempa
\else
@@ -2015,10 +2175,10 @@
\fi
\fi
% \newforeach format is '<parser>...<parser>':
- \skvxifin{\detokenize{#1...#1}}{\detokenize{#2}}{%
+ \skvxifinTF{\detokenize{#1...#1}}{\detokenize{#2}}{%
\skv@foreach@splitonguide{#1}{#2}%
\def\skv@prova##1#1##2#1...#1##3#1##4#1##5\skv@nil{%
- \skvifblank{##3}{%
+ \skvifblankTF{##3}{%
\skv@err{I can't find upper limit number or dimension,
\MessageBreak i.e., after symbool '...'}\@ehd
}{%
@@ -2032,7 +2192,7 @@
% Complete the list:
\skv@foreach@filllist@c{#1}{##1}{##2}{##3}%
% In case the list is folded on ellipsis (...):
- \skvifblank{##4}{}{\skv@foreach@filllist@a{#1}{##4#1##5}}%
+ \skvifblankTF{##4}{}{\skv@foreach@filllist@a{#1}{##4#1##5}}%
}%
}%
\expandafter\skv@prova\skv@tempa#1#1\skv@nil
@@ -2045,9 +2205,9 @@
% \skv@foreach@zerostepwarn{<lower>}{<upper>}{<pt.or.nil>}
\skvrobustdef*\skv@foreach@zerostepwarn#1#2#3{%
\skv@warn{The tokens '\detokenize{#1}', '\detokenize{#2}'
- give nil step; '1#3' used. \MessageBreak
- Maybe you used the font-dependent units \MessageBreak
- 'ex' or 'em' before \skv@begindoc@string}%
+ give nil step; '1#3' used.\MessageBreak
+ Maybe you used the font-dependent units\MessageBreak
+ 'ex' or 'em' \ifskv@latex before \skv@begindoctoks\fi}%
}
% skv@foreach@filllist@c{<parser>}{<lower1>}{<lower2>}{<upperbound>}
@@ -2093,10 +2253,10 @@
\def\skv@prova##1{%
\skv@foreach@swatrue
\skviflacus#2\then\else
- \skvifin{##1}{#2}{}\skv@foreach@swafalse
+ \skvifinTF{##1}{#2}{}\skv@foreach@swafalse
\fi
- \skvifin{##1}{#3}{}\skv@foreach@swafalse
- \skvifin{##1}{#4}{}\skv@foreach@swafalse
+ \skvifinTF{##1}{#3}{}\skv@foreach@swafalse
+ \skvifinTF{##1}{#4}{}\skv@foreach@swafalse
\ifskv@foreach@swa\else
\edef\skv@provb{\ifx\@nnil#2\@nnil\else\unexpanded{#2}, \fi}%
\skv@err{No link '##1' in one of
@@ -2143,7 +2303,7 @@
% {a^1,a^3,...,a^9} : link = ^, grow = right
% {A_1,B_1,...,E_1} : link = _, grow = left
% {1--,4--,...,16--} : link = --, grow = left
-% {1pt,4pt,...,10pt} : link = pt, grow = left (or addit. info.)
+% {1pt,4pt,...,10pt} : link = pt, grow = left, or no addit. info.
% {A_2pt,A_4pt,...,A_10pt} : link = _, grow = right
%
% The items prior to the last 2 items before '<guide>...' or before '...'
@@ -2159,7 +2319,7 @@
\begingroup
\skv@cnta\skvz@
\def\do##1#1{%
- \skvifin{...}{##1}{%
+ \skvifinTF{...}{##1}{%
\def\do####1\skv@nil{}%
}{%
\advance\skv@cnta\@ne
@@ -2205,39 +2365,43 @@
% When we say, 'try PGF format', we don't actually mean the PGF format with
% left and right guides, but the syntax '<guide>...' (ie, having only the
% left-hand-side or only the right-hand-side guide). For example,
-% {A_2pt,A_4pt,A_...,A_10pt}. \skv@foreach@trypgfformat will auto-complete
-% this list without knowledge of the values of the keys 'link' and 'grow'.
+%
+% {A_2pt,A_4pt,A_...,A_10pt} or {1pt,4pt,...pt,10pt}
+%
+% \skv@foreach@trypgfformat will auto-complete this list without
+% knowledge of the values of the keys 'link' and 'grow'.
%
% skeyval formats:
%
% {1pt,4pt,...pt,10pt} : no additional info. required
% {A_2pt,A_4pt,A_...,A_10pt} : no additional info. required
-% {1pt,4pt,...,10pt} : link = pt, grow=right (or no addit. info.)
+% {1pt,4pt,...,10pt} : link = pt, grow=right, or no addit. info.
% {A_2pt,A_4pt,...,A_10pt} : link =_, grow=right
%
-% The general PGF format (with left and right guides) is illegal here,
-% because the skeyval-for package uses the location of the guide (left or
-% right of ...) to determine the direction of growth.
+% The general PGF format (with left and right guides), e.g.,
%
% {A_2pt,A_4pt,A_...pt,A_10pt}
%
+% is illegal here, because the skeyval-for package uses the location
+% of the guide (left or right of ...) to determine the direction of growth.
+%
\skvrobustdef*\skv@foreach@trypgfformat#1#2{%
\skv@foreach@splitonguide{#1}{#2}%
\def\skv@prova##1#1##2#1##3...##4#1##5#1##6#1##7\skv@nil{%
- \skvifblank{##5}{%
+ \skvifblankTF{##5}{%
\skv@err{I can't find upper limit number or dimension,
\MessageBreak i.e., after symbool '...'}\@ehd
}{%
% \skv@foreach@filllist@a may be reentered. Hence
- \if\relax\detokenize{##1}\relax\else
+ \skviflacus{##1}\then\else
\edef\skv@foreach@filledlist{%
\skvaddlist{#1}\skv@foreach@filledlist
\skvtrimspace{##1}%
}%
\fi
\def\do####1{{\skvtrimspace{####1}}}%
- \skvifblank{##3}{%
- \skvifblank{##4}{%
+ \skvifblankTF{##3}{%
+ \skvifblankTF{##4}{%
\skv@err{No direction of growth before and/or after
\MessageBreak symbol '...'}\@ehd
}{%
@@ -2249,7 +2413,7 @@
}%
}%
}{%
- \skvifblank{##4}{%
+ \skvifblankTF{##4}{%
\def\skv@foreach@growright{00}%
\def\skv@foreach@growleft{01}%
\skvexpanded{%
@@ -2262,11 +2426,12 @@
\MessageBreak\noexpand\newforeach and \noexpand\newforeach.
\MessageBreak I know that PGF's \noexpand\foreach needs it,
\MessageBreak but I don't need it. I can
- \MessageBreak auto-fill your list without it.}\@ehd
+ \MessageBreak auto-fill your list with information
+ \MessageBreak on only one side.}\@ehd
}%
}%
% In case the list is folded on ellipsis (...):
- \skvifblank{##6}{}{\skv@foreach@filllist@a{#1}{##6#1##7}}%
+ \skvifblankTF{##6}{}{\skv@foreach@filllist@a{#1}{##6#1##7}}%
}%
}%
\expandafter\skv@prova\skv@tempa#1#1#1\skv@nil
@@ -2286,10 +2451,10 @@
\skvrobustdef*\skv@foreach@trypgfformat@a#1#2#3#4#5{%
\skv@foreach@swafalse
\skviflacus#3\then\else
- \skvxifin{#2}{#3}{}\skv@foreach@swatrue
+ \skvxifinTF{#2}{#3}{}\skv@foreach@swatrue
\fi
- \skvxifin{#2}{#4}{}\skv@foreach@swatrue
- \skvxifin{#2}{#5}{}\skv@foreach@swatrue
+ \skvxifinTF{#2}{#4}{}\skv@foreach@swatrue
+ \skvxifinTF{#2}{#5}{}\skv@foreach@swatrue
\ifskv@foreach@swa
\skv@err{Guide token '\detokenize{#2}' not found in some
\MessageBreak of the elements: I can't complete
@@ -2467,8 +2632,6 @@
}%
\expandafter\do#3#1\do#1%
}
-
-
\skvrobustdef*\skv@foreach@getcomparator{%
\begingroup
% 'unit' isn't required in alphabetic sequences:
@@ -2476,7 +2639,7 @@
\let\skvreversedo\@iden
\edef\skv@provb{\skvexpbracenext\skvreverse{\skv@foreach@step}}%
\def\skv@prova##1##2##3\skv@nil{%
- \skvxifin{,\detokenize{##2##1},}{,\skvoxdetok\skv@validunit,}{%
+ \skvxifinTF{,\detokenize{##2##1},}{,\skvoxdetok\skv@validunit,}{%
\def\skv@foreach@unit{}%
}{%
\def\skv@foreach@unit{pt}%
@@ -2551,7 +2714,7 @@
step '\skv@foreach@step' isn't an integer}\@ehd
}%
\skv@foreach@addtolist{#1}{#2}#4%
- \skvifstrcmp{#2}{#3}{}{%
+ \skvifstrcmpTF{#2}{#3}{}{%
\edef\skv@lowerlimit{#2}%
\edef\skv@upperlimit{#3}%
\skvexpandnext{\chardef\skv@lowerlimit`}\skv@lowerlimit\relax