diff options
author | Karl Berry <karl@freefriends.org> | 2012-11-06 22:35:59 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2012-11-06 22:35:59 +0000 |
commit | 6cab410e49d491c2884a037e0a134eeb2c2acda9 (patch) | |
tree | 5b7b72852382a70ac7f27f43b913d1da8f66ed12 /Master/texmf-dist/tex/latex/skeyval/skeyval-for.tex | |
parent | 705b4d8f092a56d9ae900940d265fb6f55b3033d (diff) |
skeyval (6nov12)
git-svn-id: svn://tug.org/texlive/trunk@28197 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/latex/skeyval/skeyval-for.tex')
-rw-r--r-- | Master/texmf-dist/tex/latex/skeyval/skeyval-for.tex | 687 |
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 |