diff options
author | Karl Berry <karl@freefriends.org> | 2013-02-12 23:53:37 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2013-02-12 23:53:37 +0000 |
commit | b00ddd78e03236a73df3113f75cb0c607654d5a6 (patch) | |
tree | abe63d734ede6c61983c4e8ebb8175859651b1ad /Master/texmf-dist/tex | |
parent | dcf4eb75b6ae8a7d1ebab1fc40af55709bfd8139 (diff) |
loops (12feb13)
git-svn-id: svn://tug.org/texlive/trunk@29090 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex')
-rw-r--r-- | Master/texmf-dist/tex/latex/loops/loops.sty | 678 |
1 files changed, 367 insertions, 311 deletions
diff --git a/Master/texmf-dist/tex/latex/loops/loops.sty b/Master/texmf-dist/tex/latex/loops/loops.sty index 351205fdd4e..bd11a44a18f 100644 --- a/Master/texmf-dist/tex/latex/loops/loops.sty +++ b/Master/texmf-dist/tex/latex/loops/loops.sty @@ -1,5 +1,5 @@ %++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++% -% This is file 'loops.sty', version 1.1, 2012/10/16. % +% This is file 'loops.sty', version 1.2, 2013/02/10. % % % % This package and accompanying files may be distributed and/or % % modified under the conditions of the LaTeX Project Public License, % @@ -15,7 +15,7 @@ % implied warranties of merchantability and fitness for a particular % % purpose. % % % -% Copyright (c) 2010-2012 Ahmed Musa (amusa22@gmail.com). % +% Copyright (c) 2012-2013 Ahmed Musa (amusa22@gmail.com). % %++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++% \begingroup @@ -53,7 +53,7 @@ \do 032=10,033=12,036=03,038=04,040=12,041=12,042=12,043=12,% 059=12,045=12,047=12,058=12,063=12,091=12,093=12,126=13,\do=,% -\ProvidesPackage{loops}[2012/10/16 v1.1 Loops and list processors (AM)] +\ProvidesPackage{loops}[2013/02/10 v1.2 Loops and list processors (AM)] \NeedsTeXFormat{LaTeX2e}[2011/06/27] % This is the way to load 'skeyval-for-core' here, otherwise we @@ -66,45 +66,81 @@ \directkeys*{ .every unknown option={ - \PackageWarning{loops}{Unknown option '\CurrentOption' ignored}% + \@onelevel@sanitize\CurrentOption + \PackageWarning{loops}{Unknown option '\CurrentOption' ignored} }, - .prefix=SKV, - .family=loops, + .path=SKV/loops, .holder prefix=lps@, .initialize keys after define, .new options={ .bool/verbose/true/\iflps@verbose\skv@verbosetrue\fi, }, - .copy class options and process options, + .copy class options and process options } -% \skvusetwoprev{<parser>}{<list>}{<target.item>}{<do.on.target>} -% -% Example: -% -% \skvusetwoprev{,}{a,b,c,d,e,f}{e}{} -% -\skvrobustdef*\skvusetwoprev#1#2#3#4{% - \skvifinTF{#1#3#1}{#1#2#1}{}{% - \skv@err{There is not '\detokenize{#3}' in the list}\@ehd +% \lpsdocsvlist{<parser>}{<list>}{<callback>} +% +% Execute <callback> on each item of <list>. The user has access to +% \firstprevitem, \secondprevitem, \currentitem, \firstnextitem, +% \secondnextitem (some of which may be empty), and \iflpslastitem. +% +% Examples: +% +% \def\aitems{} +% \lpsdocsvlist{,}{a,b,c,d,e,f}{% +% \def\do##1{\ifx##1\@empty\let##1\@gobble\fi}% +% \do\secondprevitem\do\firstprevitem\do\firstnextitem +% \edef\aitems{% +% \skvexpandonce\aitems\ifx\aitems\@empty\else,\fi +% \secondprevitem,\firstprevitem,\currentitem,% +% \firstnextitem,\secondnextitem +% }% +% } +% +\skvnewregister\bool{\iflpslastitem} +\skvnewlet\lpsbreakloop\skvbreaklooptrue +\skvrobustdef*\lpsdocsvlist#1#2#3{% + \skvpushfunctions\lpsdocsvlist{% + \do\lpsuserlist\do\firstprevitem\do\secondprevitem\do\currentitem + \do\firstnextitem\do\secondnextitem\do\lps@do\do\skv@callback + }\skv@csvdepth + \let\firstprevitem\@empty + \let\secondprevitem\@empty + \edef\lpsuserlist{\unexpanded{#2}}% + \edef\skv@callback{\unexpanded{#3}}% + \skvcsvnormalize[#1]\lpsuserlist + \def\lps@do##1#1##2#1##3#1{% + \edef\currentitem{\unexpanded{##1}}% + \skvifxTF\currentitem\skv@nnil{% + \skvbreakloopfalse + }{% + \skvifdefboolTF{skvbreakloop}{% + \skvbreakloopfalse + \def\lps@do####1\skv@nil#1\skv@nil#1\skv@nil#1{% + \edef\lpsremainder{\unexpanded{####1}}% + }% + }{% + \edef\firstnextitem{\unexpanded{##2}}% + \ifx\firstnextitem\skv@nnil + \lpslastitemtrue + \let\firstnextitem\@empty + \fi + \edef\secondnextitem{\unexpanded{##3}}% + \ifx\secondnextitem\skv@nnil + \let\secondnextitem\@empty + \fi + \lps@callback\relax + \let\secondprevitem\firstprevitem + \let\firstprevitem\currentitem + }% + \lps@do##2#1##3#1% + }% }% - \let\firstprev\@empty - \let\secondprev\@empty - \def\skv@tempa{#3}% - \def\skv@do##1#1{% - \ifx\skv@nnil##1\else - \def\current{##1}% - \ifx\current\skv@tempa - #4\relax - \def\skv@do####1\skv@nnil#1{}% - \else - \let\secondprev\firstprev - \let\firstprev\current - \fi - \expandafter\skv@do - \fi + \skvbreakloopfalse + \skvifemptyTF\lpsuserlist{}{% + \expandafter\lps@do\lpsuserlist#1\skv@nil#1\skv@nil#1\skv@nil#1% }% - \skv@do#2#1\skv@nnil#1% + \skvpopfunctions\lpsdocsvlist\skv@csvdepth } % Remove one element from a list. Only the first occurence of the @@ -112,7 +148,10 @@ % % \lpsremovefromlist<parser>{<element to remove>}<listcmd> % -% Eg, \def\x{1,2,3,4} \lpsremovefromlist{,}7\x +% Example: +% +% \def\x{1,2,3,4} +% \lpsremovefromlist{,}7\x % \skvrobustdef\lpsremovefromlist#1#2#3{% \begingroup @@ -180,7 +219,7 @@ % \if... % \repeat % -\skvnewregister\toks\skv@aktertoks +\skvnewregister\toks{\skv@aktertoks} \skvnewdef*\skv@aktercnt{0} \skvrobustdef*\skv@akter@defloop{% \def\skv@tempa##1##2##3{% @@ -236,7 +275,7 @@ }% }{% \skvifstrcmpTF{#1}{EOF}{% - \skv@err{'\string\repeat' not found: endless loop}\@ehd + \skv@err{'\string\repeat' not found: endless loop}\skv@ehd }{% \skvifxTF\next\@sptoken{% \skv@aktertoks\expandafter @@ -252,17 +291,17 @@ % Expandable comma loop. List is not normalized prior to parsing, and % it is not possible to terminate the loop prematurely. % -% \skvfor{<list>}<callback.macro> +% \lpsfor{<list>}<callback.macro> % % Example: % -% \skvnewregister\count\nr\nr=\tw@ +% \skvnewregister\count{\nr}\nr=\tw@ % \def\do#1{% % \let\noexpand#1% % \expandafter\noexpand\csname\skvremovescape{#1}@% % \romannumeral\nr\endcsname % } -% \edef\x{\skvfor{\cmda,\cmdb}\do} +% \edef\x{\lpsfor{\cmda,\cmdb}\do} % \show\x -> \let\cmda\cmda@ii \let\cmdb\cmdb@ii % \skvnewdef\skvfor#1#2{\skv@for@a{#2}#1,\skv@for@nil,} @@ -273,8 +312,9 @@ \skvifstrcmpTF{#2}\skv@for@nil{}{#1{#2}\skv@for@a{#1}}% }% } - -% Process non-separated (token-wise) list: +\skvnewlet\lpsfor\skvfor +% Process non-separated (token-wise) list. \ayeloop is like \skvtfor +% but uses parameter characters directly, instead of a holder macro. % % \ayeloop{<list>}\do{<1.parameter.callback>} % \ayeloop*{<listcmd>}\do{<1.parameter.callback>} @@ -288,9 +328,6 @@ % }% % }% % -% \ayeloop is like \skvtfor but uses parameter characters directly, -% instead of a holder macro. -% \skvrobustdef*\ayeloop{\skv@testst\skv@ayeloop} \skvrobustdef*\skv@ayeloop#1\do#2{% \skv@usetempst{#1}\skv@tempa @@ -317,7 +354,7 @@ } % Robust, outer-brace-preserving, multi-level, general-purpose -% non-separated values list (nsv) processor. +% non-separated values list (nsv/tsv) processor. % % \sifakaloop{<list>}{<1.parameter.callback>} % \sifakaloop*{<listcmd>}{<1.parameter.callback>} @@ -385,20 +422,20 @@ }% } -% Processing both csv and tsv/nsv lists with \foxloop. +% Processing both csv and tsv/nsv lists with \foreachfox. % -% \foxloop[<options>]{<list>}{<parametered.callback>} -% \foxloop*[<options>]{<listcmd>}{<parametered.callback>} +% \foreachfox[<options>]{<list>}{<parametered.callback>} +% \foreachfox*[<options>]{<listcmd>}{<parametered.callback>} % % 1. The <callback> is at least a one-parameter token list. % -% 2. \breakfoxloop can be used to break out of the loop. +% 2. \breakforeachfox can be used to break out of the current nest loop. +% \breakallforeachloops can be used to break out of all current loops. % % 3. When the argument is more than one (say, #1#2), the last one % must be delimited by the user-suggested <arg delimiter>. % -% 4. To permit nesting we use a stack involving the counter \foreachdepth, -% with alias \foxloopdepth. +% 4. To permit nesting we use a stack involving the counter \foreachnestdepth. % % 5. \subcallback is meant for callbacks with hash characters that may be % confused with the parameters of the main <callback>. It can be defined @@ -406,41 +443,37 @@ % % 6. Outer braces around the list items are preserved in the parsing. % -% 7. 'fox' is used here to represent an item. Eg, \currentfox, \nextfox, -% \foxcount. -% -\skvnewdef*\skv@foxloop@nnil{\skv@foxloop@nil} -\skvnewbools{lastfox} -\skvnewlet\breakfoxloop\skvbreaklooptrue -\skvnewdef*\foxloopdepth{\foreachdepth} -\skvnewdef*\foxcount{\foreachitemcount} -\skvnewdef*\currentfox{\foreachcurrentitem} -\skvnewdef*\nextfox{\foreachnextitem} -\skvnewdef*\previousfox{\foreachprevitem} -\skvnewdef*\foxlistremainder{\foreachlistremainder} -\skvnewdef*\prependtobeginfoxloop{\prependtobeginforeach} -\skvnewdef*\appendtobeginfoxloop{\appendtobeginforeach} -\skvnewdef*\prependtoendfoxloop{\prependtoendforeach} -\skvnewdef*\appendtoendfoxloop{\appendtoendforeach} +% 7. The following are available here, as in \newforeach: +% +% \foreachcurrentitem, \foreachnextitem, \foreachitemcount, +% \foreachcurrentitem, \foreachnextitem, \foreachitemcount, +% \foreachprevitem, \prependtobeginforeach, \appendtobeginforeach +% (=\atbeginforeach), \prependtoendforeach, \appendtoendforeach +% (=\atendforeach), \ifforeachlastitem, \foreachnestdepth, +% \foreachlistremainder, \skvforeachonlyinitially. +% +\skvnewregisters\bool{\iflastfox} +\skvnewlet\breakforeachfox\skvbreaklooptrue +% \atbeginforeachfox[<depth>]{<code>} +\skvnewlet\atbeginforeachfox\atbeginforeach +% \atendforeachfox[<depth>]{<code>} +\skvnewlet\atendforeachfox\atendforeach -% Define \foxloop keys. Name all the macros with 'foreach' prefix so +% Define \foreachfox keys. Name all the macros with 'foreach' prefix so % that we can avoid new command names and use the list auto-completion % scheme of \newforeach. -\quickkeys.define{loops/foxloop}{% +\quickkeys.define{loops/foreachfox}{% parser/{,}/ \def\skv@foreach@parser{#1} \skvstripouterbraces{2}\skv@foreach@parser ; - list type/csv/ - \def\skv@foreach@listtype{#1} - /csv,kv,tsv,nsv - ; + list type/csv/\def\skv@foreach@listtype{#1}/csv,kv,tsv,nsv; arg,args,arg pattern/##1/ \edef\skv@foreach@paramlist{\unexpanded{#1}} \skvstripouterbraces{1}\skv@foreach@paramlist ; - list breaker/\listbreaker/\def\skv@listbreakertoks{#1}; - list pauser/\listpauser/\def\skv@listpausertoks{#1}; + list breaker/\skvlistbreaker/\def\skv@listbreakertoks{#1}; + list pauser/\skvlistpauser/\def\skv@listpausertoks{#1}; normalize list/true/ \edef\skv@foreach@normalizelist{0\skvifstrcmpTF{#1}{true}01} /true,false @@ -449,42 +482,50 @@ \edef\skv@foreach@useempty{0\skvifstrcmpTF{#1}{true}01} /true,false ; - .exec/ - \let\skv@foreach@exittester\@secondoftwo + .exec/\let\skv@foreach@exittester\@secondoftwo; + break,loop stopper,exit when/\if01\fi/ + \edef\skv@tempa{\unexpanded{#1}} + \skvstripouterbraces{2}\skv@tempa + \skvexpbracenext\skv@foreach@maketester\skv@tempa + \skv@foreach@exittester\@ne ; - loop stopper,exit when/\if01\fi/ - \ifskvindef\else - \edef\skv@tempa{\unexpanded{#1}} - \skvstripouterbraces{2}\skv@tempa - \expandafter\skv@foreach@maketester\expandafter - {\skv@tempa}\skv@foreach@exittester - \fi + .exec/\let\skv@foreach@continuetester\@secondoftwo; + continue,ignore callback/\if01\fi/ + \edef\skv@tempa{\unexpanded{#1}}% + \skvstripouterbraces{2}\skv@tempa + \skvexpbracenext\skv@foreach@maketester\skv@tempa + \skv@foreach@continuetester\skvz@ ; - item counter,counter/\@nil/ - \def\skv@foreach@itemcounter{#1} + item counter,counter/\foreachdefaultitemcounter/ + \skvifescapedTF{#1}{% + \def\skv@foreach@itemcounter{#1}% + }{% + \skv@err{Non-escaped value '\detokenize{#1}' + \MessageBreak for key 'item counter'}\skv@ehd + }% + ; + process up to,process up to number// + \skviflacus#1\then\else + \skvensureinteger{process up to}{#1}% + \def\skv@foreach@processupto{#1}% + \skvstripouterbraces{2}\skv@foreach@processupto + \fi ; % This default value of 'link' is required by \skv@foreach@filllist: .exec/\def\skv@foreach@link{\@nil}; link/\@nil/ - \ifskvindef\else + \edef\skv@prova{\unexpanded{#1}} + \ifx\skv@prova\@nnil\else \edef\skv@foreach@link{\unexpanded{#1}} \skvstripouterbraces{2}\skv@foreach@link - \ifnum0>\numexpr0\ifx\skv@foreach@link\@empty-1\else - \ifx\skv@foreach@link\@nnil-1\else+0\fi\fi\relax\relax - \skv@err{The key 'link' doesn't accept empty/blank values}\@ehd - \fi \fi ; grow/\@nil/ - \ifskvindef\else - \edef\skv@prova{\unexpanded{#1}}% - \ifx\skv@prova\@nnil - \skv@err{Value required for key 'grow'}\@ehd - \else - \skvcsedef{skv@foreach@grow#1}{00}% - \edef\skv@prova{\skvifstrcmpTF{#1}{left}{right}{left}}% - \skvcsedef{skv@foreach@grow\skv@prova}{01}% - \fi + \edef\skv@prova{\unexpanded{#1}}% + \ifx\skv@prova\@nnil\else + \skvcsedef{skv@foreach@grow#1}{00}% + \edef\skv@prova{\skvifstrcmpTF{#1}{left}{right}{left}}% + \skvcsedef{skv@foreach@grow\skv@prova}{01}% \fi /left,right ; @@ -493,17 +534,13 @@ \def\skv@foreach@growright{01}% ; grow left/true/ - \ifskvindef\else - \edef\skv@foreach@growleft{0\skvifstrcmpTF{true}{#1}01}% - \edef\skv@foreach@growright{0\skvifstrcmpTF{true}{#1}10}% - \fi + \edef\skv@foreach@growleft{0\skvifstrcmpTF{true}{#1}01}% + \edef\skv@foreach@growright{0\skvifstrcmpTF{true}{#1}10}% /true,false ; grow right/true/ - \ifskvindef\else - \edef\skv@foreach@growright{0\skvifstrcmpTF{true}{#1}01}% - \edef\skv@foreach@growleft{0\skvifstrcmpTF{true}{#1}10}% - \fi + \edef\skv@foreach@growright{0\skvifstrcmpTF{true}{#1}01}% + \edef\skv@foreach@growleft{0\skvifstrcmpTF{true}{#1}10}% /true,false ; % Keep the decimals in rounded numbers or dimensions when list is @@ -535,10 +572,10 @@ ; % Eg, 'evaluate = #1 as \x using \numexpr#1*2'. % Since the parameters haven't assumed arguments, we defer the - % call to \skv@foxloop@parseevaluate until the arguments are known. + % call to \skv@foreachfox@parseevaluate until the arguments are known. evaluate/\@nil/ \skv@foreach@ifacceptkv{#1}{% - \skv@foxloop@parseevaluate{#1}% + \skv@foreachfox@parseevaluate{#1}% }% ; % Eg, @@ -546,13 +583,13 @@ % 'count in = \p all #1 satisfying \ifnum#1>4\fi' count in,count/\@nil/ \skv@foreach@ifacceptkv{#1}{% - \skv@foxloop@parsecountin{#1}% + \skv@foreachfox@parsecountin{#1}% }% ; % Eg, remember=#1 as \y initially A remember/\@nil/ \skv@foreach@ifacceptkv{#1}{% - \skv@foxloop@parseremember{#1}% + \skv@foreachfox@parseremember{#1}% }% ; reverse list,reverse,reflect/true/ @@ -560,22 +597,12 @@ /true,false ; } - -% Set up \foxloop defaults: -\quickkeys.set{loops/foxloop}{% - parser={,}, - list type=csv, - arg=#1, - list breaker=\listbreaker, - list pauser=\listpauser, - normalize list=true, - use empty=false, - keep decimals=true, - keep high decimals=false, - expand before fill=false, - reverse list=false, - expand list once=false, - expand list twice=false, +\quickkeys.preset{loops/foreachfox}{% + parser={,},list type=csv,arg=#1,loop stopper, + list breaker=\skvlistbreaker,list pauser=\skvlistpauser, + normalize list=true,use empty=false,keep decimals=true, + keep high decimals=false,expand before fill=false, + reverse list=false,expand list once=false,expand list twice=false, expand list fully=false, } @@ -583,10 +610,10 @@ % % Eg, 'evaluate = #1 as \x using \numexpr#1*2'. % -% \skv@foxloop@parseevaluate differs from \skv@foreach@parseevaluate +% \skv@foreachfox@parseevaluate differs from \skv@foreach@parseevaluate % because #1 here is likely to be a non-macro. % -\skvrobustdef*\skv@foxloop@parseevaluate#1{% +\skvrobustdef*\skv@foreachfox@parseevaluate#1{% \begingroup \def\skv@tempxifin##1##2{% \skvxifinTF{\detokenize{##1}}{\detokenize{##2}}% @@ -599,19 +626,19 @@ \edef\skv@provc{\skvtrimspace{##3}}% \ifx\skv@prova\@empty \skv@err{Value of key 'evaluate': - \MessageBreak no quantity to evaluate}\@ehd + \MessageBreak no quantity to evaluate}\skv@ehd \fi \ifx\skv@provb\@empty \skv@err{Value of key 'evaluate' has no receiving macro, - \MessageBreak i.e., after 'as'}\@ehd + \MessageBreak i.e., after 'as'}\skv@ehd \else \expandafter\skvifescapedTF\expandafter{\skv@provb}{}{% \skv@err{Value of key 'evaluate': receiving macro - \MessageBreak \skvoxdetok\skv@provb not escaped}\@ehd + \MessageBreak \skvoxdetok\skv@provb not escaped}\skv@ehd }% \fi \ifx\skv@provc\@empty - \skv@err{Value of key 'evaluate' has no formula}\@ehd + \skv@err{Value of key 'evaluate' has no formula}\skv@ehd \fi \skv@tempxifin{\pgfmathparse}{##3}{% \def\skv@tempc####1\pgfmathparse####2\skv@nil{% @@ -620,11 +647,11 @@ \skv@foreach@swatrue \else \skv@err{\noexpand\pgfmathparse isn't defined; - \MessageBreak maybe 'pgfmath' isn't loaded}\@ehd + \MessageBreak maybe 'pgfmath' isn't loaded}\skv@ehd \fi \else \skv@err{Invalid token \detokenize{####1} - \MessageBreak before \string\pgfmathparse}\@ehd + \MessageBreak before \string\pgfmathparse}\skv@ehd \fi }% \expandafter\skv@tempc\skv@provc\skv@nil @@ -648,7 +675,7 @@ \skv@tempa#1\skv@nil }{% \skv@err{Value of key 'evaluate': - \MessageBreak there is 'using', but no 'as'}\@ehd + \MessageBreak there is 'using', but no 'as'}\skv@ehd }% }{% % No formula given: @@ -657,10 +684,10 @@ \def\skv@tempb##1as##2##3\skv@nil{% \ifx\@nnil##1\@nnil \skv@err{Value of key 'evaluate' has no - \MessageBreak quantity to evaluate}\@ehd + \MessageBreak quantity to evaluate}\skv@ehd \else \ifx\@nnil##2% - \skv@err{Value of key 'evaluate' has no receiving macro}\@ehd + \skv@err{Value of key 'evaluate' has no receiving macro}\skv@ehd \else \skv@tempa##1as##2using##1\skv@nil \fi @@ -668,14 +695,14 @@ }% \skv@tempb#1{\@nnil}\skv@nil }{% - % No 'as' or 'using'. In \foxloop, #1 is not guaranteed + % No 'as' or 'using'. In \foreachfox, #1 is not guaranteed % to be a macro. Hence raise error here: - \skv@err{Value of key 'evaluate' has no 'as'}\@ehd + \skv@err{Value of key 'evaluate' has no 'as'}\skv@ehd }% }% \skv@foreach@addtocallback{pre}{% \ifskv@foreach@swa - % Here, <formula> may have the syntax \pgfmathresult{<token>}. + % Here, <formula> may have the syntax \pgfmathparse{<token>}. \skvexpandonce\skv@provc \let\skvexpandonce\skv@provb\noexpand\pgfmathresult \else @@ -704,15 +731,15 @@ % % '\foreach \x [count=\xi from 2] in {a,...,e}'. % -% Generic counting is available in \foxloop by default, without -% user request. The macros \currentfox, \foxcount, \nextfox are -% always available on each nesting level. The boolean \iflastfox -% is also always available, to indicate when the last item of -% the list has been reached: +% Generic counting is available in \foreachfox by default, without +% user request. The macros \foreachcurrentitem, \foreachitemcount, +% \foreachnextitem are always available on each nesting level. +% The boolean \ifforeachlastitem is also always available, to indicate +% when the last item of the list has been reached: % -% \iflastfox\typeout{Processing last entry of the list} \fi +% \ifforeachlastitem\typeout{Processing last entry of the list} \fi % -\skvrobustdef*\skv@foxloop@parsecountin#1{% +\skvrobustdef*\skv@foreachfox@parsecountin#1{% \begingroup \def\skv@tempxifin##1##2{% \skvxifinTF{\detokenize{##1}}{\detokenize{##2}}% @@ -730,11 +757,11 @@ \edef\skv@provc{\skvtrimspace{##3}}% \edef\skv@provd{\skvtrimspace{##4}}% \ifx\skv@prova\@empty - \skv@err{Value of key 'count' has no counter macro}\@ehd + \skv@err{Value of key 'count' has no counter macro}\skv@ehd \else \expandafter\skvifescapedTF\expandafter{\skv@prova}{}{% \skv@err{Value of key 'count':\MessageBreak - counter macro \skvoxdetok\skv@prova not escaped}\@ehd + counter macro \skvoxdetok\skv@prova not escaped}\skv@ehd }% \fi \ifx\skv@provd\@empty @@ -744,7 +771,7 @@ \expandafter\let\skv@prova\skv@provd }{% \skv@err{Value of key 'count':\MessageBreak - initial \skvoxdetok\skv@provd not an integer}\@ehd + initial \skvoxdetok\skv@provd not an integer}\skv@ehd }% \fi \skv@foreach@swafalse @@ -758,7 +785,7 @@ \skv@foreach@swatrue % \skv@tester is the second argument of \skv@foreach@maketester, % which is used below: - \skvexpbracenext\skv@foreach@maketester\skv@provc\skv@tester + \skvexpbracenext\skv@foreach@maketester\skv@provc\skv@tester\skvz@ \fi \fi }% @@ -768,7 +795,7 @@ \skv@tempa#1\skv@nil }{% \skv@err{Value of key 'count': - \MessageBreak there is 'satisfying', but no 'all'}\@ehd + \MessageBreak there is 'satisfying', but no 'all'}\skv@ehd }% }{% \skv@tempxifin{all}{#1}{% @@ -776,14 +803,14 @@ }{% % No 'all' and 'satisfying': #1 should be only the counter macro: \ifx\@nnil#1\@nnil - \skv@err{Value of key 'count': no counter macro}\@ehd + \skv@err{Value of key 'count': no counter macro}\skv@ehd \else \skvifntypeTF{#1}{% \skv@tempa#1all satisfying\skv@nil }{% \skv@err{Value of key 'count in': more than 1 \MessageBreak token '\detokenize{#1}'. - \MessageBreak I can't find counter macro}\@ehd + \MessageBreak I can't find counter macro}\skv@ehd }% \fi }% @@ -809,7 +836,7 @@ % remember=<holder.macro> as <child.macro> initially <value> % -\skvrobustdef*\skv@foxloop@parseremember#1{% +\skvrobustdef*\skv@foreachfox@parseremember#1{% \begingroup \def\skv@tempxifin##1##2{% \skvxifinTF{\detokenize{##1}}{\detokenize{##2}}% @@ -817,7 +844,7 @@ \skv@tempxifin{(}{#1}{% \skv@err{Value of key 'remember': '(' found. \MessageBreak I don't accept this PGF format. - \MessageBreak remove the parenthesis '()'}\@ehd + \MessageBreak Remove the parenthesis around '(<your input>)'}\skv@ehd }{}% \def\skv@tempa##1as##2initially##3\skv@nil{% \edef\skv@prova{\skvtrimspace{##1}}% @@ -825,17 +852,17 @@ \edef\skv@provc{\skvtrimspace{##3}}% \skv@foreach@swafalse \ifx\skv@prova\@empty - \skv@err{Value of key 'remember' has no value to remember}\@ehd + \skv@err{Value of key 'remember' has no value to remember}\skv@ehd \fi \ifx\skv@provb\@empty \skv@err{Value of key 'remember' has no child macro; - \MessageBreak i.e., no macro after 'as'}\@ehd + \MessageBreak i.e., no macro after 'as'}\skv@ehd \else \expandafter\skvifescapedTF\expandafter{\skv@provb}{% \skv@foreach@swatrue }{% \skv@err{Value of key 'remember': - \MessageBreak child \skvoxdetok\skv@provb not escaped}\@ehd + \MessageBreak child \skvoxdetok\skv@provb not escaped}\skv@ehd }% \fi }% @@ -844,7 +871,7 @@ \skv@tempa#1\skv@nil }{% \skv@err{Value of key 'remember': - \MessageBreak there is 'initially', but no 'as'}\@ehd + \MessageBreak there is 'initially', but no 'as'}\skv@ehd }% }{% \skv@tempxifin{as}{#1}{% @@ -853,9 +880,9 @@ % No 'as' and 'initially': \ifx\@nnil#1\@nnil\else % Unlike in \newforeach, we can't create an automatic retainer - % macro here, since \foxloop uses parameters instead of + % macro here, since \foreachfox uses parameters instead of % holder macros. - \skv@err{Value of key 'remember' is incomplete: no 'as'}\@ehd + \skv@err{Value of key 'remember' is incomplete: no 'as'}\skv@ehd \fi }% }% @@ -884,40 +911,62 @@ }% } -\skvnewdef*\skv@foxloop@kvlist{} -% \setupfoxloop{<kvlist>} -\skvrobustdef*\setupfoxloop#1{% +\skvnewdef*\skv@foreachfox@kvlist{} +% \setupforeachfox{<kvlist>} +\skvrobustdef*\setupforeachfox#1{% \skvifblankTF{#1}{}{% - \skvaddtolist\skv@foxloop@kvlist{#1}% + \skvaddtolist\skv@foreachfox@kvlist{#1}% }% } -\skvrobustdef*\skv@foxloop@setkeys#1{% - \def\reserved@a{\quickkeys.set{loops/foxloop}}% - \expandafter\reserved@a\expandafter{\skv@foxloop@kvlist,#1}% +\skvrobustdef*\skv@foreachfox@setkeys#1{% + \def\reserved@a{\quickkeys.set{loops/foreachfox}}% + \expandafter\reserved@a\expandafter{\skv@foreachfox@kvlist,#1}% } - -% \atbeginfoxloop[<depth>]{<code>} -\skvnewlet\atbeginfoxloop\atbeginforeach -% \atendfoxloop[<depth>]{<code>} -\skvnewlet\atendfoxloop\atendforeach - -\skvrobustdef*\foxloop{\skv@teststopt\skv@foxloop{}} -\skvnewlet\foreachfox\foxloop -\skvrobustdef*\skv@foxloop[#1]#2#3{% +\skvrobustdef*\foreachfox{% + \skvifnextchar i{% + \skv@foreachfox@prescan@a + }{% + \skv@teststopt\skv@foreachfox@prescan@b{}% + }% +} +\skvrobustdef*\skv@foreachfox@prescan@a#1#2{% + \skvifstrcmpTF{#1#2}{in}{% + \skv@teststopt\skv@foreachfox@prescan@b{}% + }{% + \skv@err{I have found 'i' before opening brace or + \MessageBreak bracket, but no 'in'}\skv@ehd + }% +} +\skvrobustdef*\skv@foreachfox@prescan@b[#1]{% + \skvifnextchar i{% + \skv@foreachfox@prescan@c[#1]% + }{% + \skv@foreachfox@a[#1]% + }% +} +\skvrobustdef*\skv@foreachfox@prescan@c[#1]#2#3{% + \skvifstrcmpTF{#2#3}{in}{% + \skv@foreachfox@a[#1]% + }{% + \skv@err{I have found 'i' after '[]', but no 'in'}\skv@ehd + }% +} +\skvrobustdef*\skv@foreachfox@a[#1]#2#3{% \edef\skv@foreach@seenstar{0\ifskv@tempst0\else1\fi}% \skv@foreach@pushstate \skv@foreach@latehookerr \def\foreachitemcount{0}% - \def\skv@foreach@callback{}% - \def\skv@foreach@afterprecallback{}% - \def\skv@foreach@precallback{}% - \def\skv@foreach@postcallback{}% - \def\skv@foreach@onlyinitially{}% - \skv@foxloop@setkeys{#1}% + \def\do##1{\def##1{}}% + \do\skv@foreach@itemcounter\do\skv@foreach@processupto + \do\skv@foreach@callback\do\skv@foreach@auxcallback + \do\skv@foreach@precallback\do\skv@foreach@afterprecallback + \do\skv@foreach@postcallback\do\skv@foreach@onlyinitially + \skv@foreachfox@setkeys{#1}% \if\skv@foreach@seenstar \def\skv@foreach@expandlistonce{00}% \fi \ifcase0% + % Take only one case: \if\skv@foreach@expandlistonce\else \if\skv@foreach@expandlisttwice\else \if\skv@foreach@expandlistfully\else 1\fi\fi\fi\relax @@ -928,8 +977,7 @@ \ifskv@verbose \skv@warn{One-item list '\detokenize{#2}' is a macro. \MessageBreak If your list is indeed a macro, you can - \MessageBreak either put star (*) after - \detokenize{\foxloop or \foreachfox} + \MessageBreak either put star (*) after \noexpand\foreachfox \MessageBreak or use the key 'expand list once' \MessageBreak or 'expand list twice' or 'list is a macro', etc}% \fi @@ -953,7 +1001,9 @@ \fi {#2}% }% - \skvcsuse{skv@foreach@atbeginhook@\skvrom\foreachdepth}% + \skvcsuse{skv@foreach@atbeginhook@\skvrom\foreachnestdepth}% + \skvifdefTF\foreachprevitem{}{\def\foreachprevitem{}}% + % Define the loop callback: \edef\reserved@a{% \skvexpandonce\skv@foreach@precallback \ifx\skv@foreach@onlyinitially\@empty\else @@ -961,10 +1011,18 @@ \skvexpandonce\skv@foreach@onlyinitially \noexpand\fi \fi - \unexpanded{#3}% - \skvexpandonce\skv@foreach@postcallback + \ifx\skv@foreach@continuetester\@secondoftwo + \noexpand\skv@foreach@continuetester + \else + % We want to expose the parameter characters in + % \skv@foreach@continuetester: + \skvexpandonce\skv@foreach@continuetester + \fi + {}{% + \unexpanded{#3}% + \skvexpandonce\skv@foreach@postcallback + }% }% - % Define the user callback: \edef\reserved@b{% \def\noexpand\skv@foreach@callback\skvexpandonce \skv@foreach@paramlist\noexpand\foreacheov @@ -972,18 +1030,21 @@ \expandafter\reserved@b\expandafter{\reserved@a}% \skvxifstrcmpTF\skv@foreach@listtype{csv}{% \def\skv@foreach@lookahead@a##1{% - \def\skv@foreach@continue{##1.}% + \def\skv@foreach@picknext{##1.}% \futurelet\skv@foreach@next\skv@foreach@lookahead@b }% - \def\skv@foreach@lookahead@c[##1]{\skv@foreach@continue[{##1}]}% - \def\skv@foreach@lookahead@d(##1){\skv@foreach@continue({##1})}% + \def\skv@foreach@lookahead@c[##1]{\skv@foreach@picknext[{##1}]}% + \def\skv@foreach@lookahead@d(##1){\skv@foreach@picknext({##1})}% }{% + % Token list (nsv/tsv): \def\skv@foreach@lookahead@a##1{% - \let\skv@foreach@continue##1% + \let\skv@foreach@picknext##1% \futurelet\skv@foreach@next\skv@foreach@lookahead@b }% - \def\skv@foreach@lookahead@c[##1]{\skv@foreach@continue{[##1]}}% - \def\skv@foreach@lookahead@d(##1){\skv@foreach@continue{(##1)}}% + % These \skv@foreach@lookahead@c and \skv@foreach@lookahead@d + % differ from those for 'csv' list (above): + \def\skv@foreach@lookahead@c[##1]{\skv@foreach@picknext{[##1]}}% + \def\skv@foreach@lookahead@d(##1){\skv@foreach@picknext{(##1)}}% }% \def\skv@foreach@lookahead@b{% \skvifxTF\skv@foreach@next[{% @@ -992,20 +1053,23 @@ \skvifxTF\skv@foreach@next({% \skv@foreach@parenthtrue\skv@foreach@lookahead@d }{% - \skv@foreach@parenthfalse\skv@foreach@continue + \skv@foreach@parenthfalse\skv@foreach@picknext }% }% }% - \skvbreakloopfalse\lastfoxfalse + \ifnum\foreachnestdepth=\skvz@ + \breakallforeachloopsfalse + \fi + \skvbreakloopfalse\foreachlastitemfalse\lastfoxfalse \def\reserved@a##1{% \skv@setupgetnextfox{##1}% \skvxifstrcmpTF\skv@foreach@listtype{csv}{% \if\skv@foreach@normalizelist \skv@foreach@normalize[##1]\skv@foreach@userlist \fi - \def\skv@foreach@do####1##1####2\skv@foxloop@stop{% - \edef\currentfox{\skvexpandonce{\@gobble####1}}% - \skv@foxloop@a{##1}{####2}{csv}% + \def\skv@foreach@do@a####1##1####2\skv@foreach@stop{% + \edef\foreachcurrentitem{\skvexpandonce{\@gobble####1}}% + \skv@foreachfox@b{##1}{####2}{csv}% }% \skvifemptyTF\skv@foreach@userlist{}{% \expandafter\skv@foreach@filllist\expandafter @@ -1015,135 +1079,141 @@ {\skv@foreach@parser}\skv@foreach@userlist \fi }% - % If \skv@foreach@userlist is empty, \currentfox in - % \skv@foxloop@b will terminate the loop. - \expandafter\skv@foreach@lookahead@a\expandafter\skv@foreach@do - \skv@foreach@userlist##1\skv@foxloop@nil##1\skv@foxloop@stop + % If \skv@foreach@userlist is empty, \foreachcurrentitem in + % \skv@foreachfox@c will terminate the loop. + \expandafter\skv@foreach@lookahead@a\expandafter\skv@foreach@do@a + \skv@foreach@userlist##1\skv@foreach@nil##1\skv@foreach@stop }{% - \if\skv@foreach@normalizelist + \if\skv@foreach@normalizelist\skvafterfi \edef\skv@foreach@userlist{% \skvexpbracenext\skvtsvnormalize\skv@foreach@userlist }% \fi - \def\skv@foreach@do{% + \def\skv@foreach@do@a{% \let\bgroup\relax - \futurelet\skv@foreach@next\skv@foreach@do@a + \futurelet\skv@foreach@next\skv@foreach@do@b }% - \def\skv@foreach@do@a####1####2\skv@foxloop@stop{% + \def\skv@foreach@do@b####1####2\skv@foreach@stop{% \let\bgroup\skv@orig@bgroup \ifskv@foreach@parenth - \edef\currentfox{\unexpanded{####1}}% + \edef\foreachcurrentitem{\unexpanded{####1}}% \else \skvifxTF\skv@foreach@next\bgroup{% - \edef\currentfox{{\unexpanded{####1}}}% + \edef\foreachcurrentitem{{\unexpanded{####1}}}% }{% - \edef\currentfox{\unexpanded{####1}}% + \edef\foreachcurrentitem{\unexpanded{####1}}% }% \fi - \skv@foxloop@a{}{####2}{tsv}% + \skv@foreachfox@b{}{####2}{tsv}% }% - \expandafter\skv@foreach@lookahead@a\expandafter\skv@foreach@do - \skv@foreach@userlist\skv@foxloop@nil\skv@foxloop@stop + \expandafter\skv@foreach@lookahead@a\expandafter\skv@foreach@do@a + \skv@foreach@userlist\skv@foreach@nil\skv@foreach@stop }% }% \expandafter\reserved@a\expandafter{\skv@foreach@parser}% - \skvcsuse{skv@foreach@atendhook@\romannumeral\foreachdepth}% + \skvcsuse{skv@foreach@atendhook@\romannumeral\foreachnestdepth}% \skv@foreach@popstate } % \skv@setupgetnextfox<parser> \skvrobustdef*\skv@setupgetnextfox#1{% \skvxifstrcmpTF\skv@foreach@listtype{csv}{% - \def\skv@foreach@getnext##1#1##2\skv@foxloop@stop{% - \edef\nextfox{\skvexpandonce{\@gobble##1}}% - % See \skv@foxloop@b for \lastfoxtrue. + \def\skv@foreach@getnext##1#1##2\skv@foreach@stop{% + \edef\foreachnextitem{\skvexpandonce{\@gobble##1}}% + % See \skv@foreachfox@c for \foreachlastitemtrue. }% }{% \def\skv@foreach@getnext{% - \begingroup \let\bgroup\relax \futurelet\skv@foreach@next\skv@foreach@g@tnext }% - \def\skv@foreach@g@tnext##1##2\skv@foxloop@stop{% + \def\skv@foreach@g@tnext##1##2\skv@foreach@stop{% \let\bgroup\skv@orig@bgroup \ifskv@foreach@parenth - \edef\nextfox{\unexpanded{##1}}% + \edef\foreachnextitem{\unexpanded{##1}}% \else \skvifxTF\skv@foreach@next\bgroup{% - \edef\nextfox{{\unexpanded{##1}}}% + \edef\foreachnextitem{{\unexpanded{##1}}}% }{% - \edef\nextfox{\unexpanded{##1}}% + \edef\foreachnextitem{\unexpanded{##1}}% }% \fi }% }% } -% \skv@foxloop@a<parser><remainder><list.type> -\skvrobustdef*\skv@foxloop@a#1#2#3{% - \skvifxTF\currentfox\skv@foxloop@nnil{% - \skvbreakloopfalse\lastfoxfalse +% \skv@foreachfox@b<parser><remainder><list.type> +\skvrobustdef*\skv@foreachfox@b#1#2#3{% + \skvifxTF\foreachcurrentitem\skv@foreach@nnil{% + \skvbreakloopfalse\foreachlastitemfalse\lastfoxfalse }{% - \skvifxTF\currentfox\skv@listbreakertoks{% - \skv@foxloop@getrm{#1}{#2}% + \skvifxTF\foreachcurrentitem\skv@listbreakertoks{% + \skv@foreachfox@getrm{#1}{#2}% }{% - \skvifxTF\currentfox\skv@listpausertoks{% + \skvifxTF\foreachcurrentitem\skv@listpausertoks{% \message{^^J! List pause: ^^JType x or X to quit, or <RETURN> to proceed^^J}% \bgroup\endlinechar\m@ne\global\read-1 to\@gtempa\egroup \skvexpandarg\lowercase{\def\noexpand\@gtempa{\@gtempa}}% \skvxifstrcmpTF\@gtempa{x}{% - \skv@foxloop@getrm{#1}{#2}% + \skv@foreachfox@getrm{#1}{#2}% }{% - \skv@foxloop@b{#1}{#2}{#3}% + \skv@foreachfox@c{#1}{#2}{#3}% }% }{% - \skv@foxloop@b{#1}{#2}{#3}% + \skv@foreachfox@c{#1}{#2}{#3}% }% }% }% } -% \skv@foxloop@b<parser><remainder><list.type> -\skvrobustdef*\skv@foxloop@b#1#2#3{% - \skv@foreach@lookahead@a\skv@foreach@getnext#2\skv@foxloop@stop - \ifx\nextfox\skv@foxloop@nnil - \lastfoxtrue\def\nextfox{}% +% \skv@foreachfox@c<parser><remainder><list.type> +\skvrobustdef*\skv@foreachfox@c#1#2#3{% + \skv@foreach@lookahead@a\skv@foreach@getnext#2\skv@foreach@stop + \ifx\foreachnextitem\skv@foreach@nnil + \foreachlastitemtrue\lastfoxtrue + \def\foreachnextitem{}% \fi \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 - \expandafter\let\skv@foreach@itemcounter\foreachitemcount + \ifx\skv@foreach@itemcounter\@empty\else + \expandafter\let\skv@foreach@itemcounter\foreachitemcount \fi - \skvifemptyTF\currentfox{% - \if\skv@foreach@useempty - \expandafter\skv@foreach@callback\expandafter\foreacheov + \skvifemptyTF\foreachcurrentitem{% + \if\skv@foreach@useempty\skvafterfi + \skv@foreach@callback\foreacheov \fi }{% - % Tes for \listpauser, in case the user decides to continue - % after \listpauser has been picked: - \skvifxTF\currentfox\skv@listpausertoks{}{% + % Test for \skvlistpauser, in case the user decides to continue + % after \skvlistpauser has been picked: + \skvifxTF\foreachcurrentitem\skv@listpausertoks{}{% \skvifxTF\skv@foreach@paramlist\skv@simplearg{% - \expandafter\skv@foreach@callback\expandafter - {\currentfox}\foreacheov + \skvexpbracenext\skv@foreach@callback\foreachcurrentitem\foreacheov }{% - \expandafter\skv@foreach@callback\currentfox\foreacheov + % Incomplete items like 3 in {1/a,2/b,3} can't be handled by + % \foreachfox; see \newforeach. + \expandafter\skv@foreach@callback\foreachcurrentitem\foreacheov }% + \let\foreachprevitem\foreachcurrentitem }% }% - \skv@foreach@exittester{\skvbreakloop}{}% + \ifx\skv@foreach@processupto\@empty\else + \ifnum\foreachitemcount<\skv@foreach@processupto\relax\else + \skvbreakloop + \fi + \fi \skvifdefboolTF{skvbreakloop}{% - \skvbreakloopfalse\lastfoxfalse - \skv@foxloop@getrm{#1}{#2}% + \ifbreakallforeachloops\else + \skvbreakloopfalse + \fi + \foreachlastitemfalse\lastfoxfalse + \skv@foreachfox@getrm{#1}{#2}% }{% - \skv@foreach@lookahead@a\skv@foreach@do#2\skv@foxloop@stop + \skv@foreach@lookahead@a\skv@foreach@do@a#2\skv@foreach@stop }% } -% \skv@foxloop@getrm<parser><remaining.items> -\skvrobustdef*\skv@foxloop@getrm#1#2{% +% \skv@foreachfox@getrm<parser><remaining.items> +\skvrobustdef*\skv@foreachfox@getrm#1#2{% \begingroup - \def\reserved@a##1\skv@foxloop@nil#1{% + \def\reserved@a##1\skv@foreach@nil#1{% \endgroup - \edef\foxlistremainder{\unexpanded{##1}}% + \edef\foreachlistremainder{\unexpanded{##1}}% }% \reserved@a#2% } @@ -1222,7 +1292,7 @@ \skvbreakloopfalse\lastcicadafalse }{% \edef\cicadacount{\the\numexpr\cicadacount+1}% - \skv@cicada@lookahead\skv@cicada@getnext##2\skv@cicada@stop + \skv@cicada@lookahead@a\skv@cicada@getnext##2\skv@cicada@stop \skvexpandbracenext\skv@cicada@callback\currentcicada\relax \skvifcondFT#3\fi{}\skvbreakloop \skvifdefboolTF{skvbreakloop}{% @@ -1235,33 +1305,33 @@ \skv@prova##2% }{% \let\lastcicada\currentcicada - \skv@cicada@lookahead\skv@cicada@do##2\skv@cicada@stop + \skv@cicada@lookahead@a\skv@cicada@do##2\skv@cicada@stop }% }% }% }% - \def\skv@cicada@lookahead##1{% - \def\skv@cicada@continue{##1.}% - \futurelet\skv@next\skv@cicada@lookahead@a + \def\skv@cicada@lookahead@a##1{% + \def\skv@cicada@picknext{##1.}% + \futurelet\skv@next\skv@cicada@lookahead@b }% - \def\skv@cicada@lookahead@a{% + \def\skv@cicada@lookahead@b{% \ifx\skv@next[% - \expandafter\skv@cicada@lookahead@b + \expandafter\skv@cicada@lookahead@c \else \ifx\skv@next(% - \expandafter\expandafter\expandafter\skv@cicada@lookahead@c + \expandafter\expandafter\expandafter\skv@cicada@lookahead@d \else - \expandafter\expandafter\expandafter\skv@cicada@continue + \expandafter\expandafter\expandafter\skv@cicada@picknext \fi \fi }% - \def\skv@cicada@lookahead@b[##1]{\skv@cicada@continue[{##1}]}% - \def\skv@cicada@lookahead@c(##1){\skv@cicada@continue({##1})}% + \def\skv@cicada@lookahead@c[##1]{\skv@cicada@picknext[{##1}]}% + \def\skv@cicada@lookahead@d(##1){\skv@cicada@picknext({##1})}% \skvbreakloopfalse\lastcicadafalse \skvifxTF\skv@cicada@userlist\@empty{% \ifskvprocessempty\skv@cicada@callback{}\fi }{% - \skvexpandnext{\skv@cicada@lookahead\skv@cicada@do}% + \skvexpandnext{\skv@cicada@lookahead@a\skv@cicada@do}% \skv@cicada@userlist#1\skv@cicada@nil#1\skv@cicada@stop }% \skvpopstate\skv@cicada@state\cicadaloopdepth @@ -1270,11 +1340,12 @@ % \cicadiloop[<parser>]{<list>}<\if...>\fi{<ini-code>}{<1.parameter.code>} % \cicadiloop*[<parser>]{<listcmd>}<\if...>\fi{<ini-code>}{<1.parameter.code>} % -% It is easy to forget to turn conditional #3 off before commencing +% It is easy to forget to turn conditional <\if...> off before commencing % the loop, especially if it is a boolean. The conditional might have % been set true before calling \cicadaloop, and this may invalidate -% later tests to terminate the loop prematurely. #4 can be used to turn -% the condtional off before commencing the loop. +% later tests to terminate the loop prematurely. <ini-code> can be used +% to turn the condtional off before commencing the loop. This forces the +% user to heed this term. % \skvrobustdef*\cicadiloop{\skv@teststopt\skv@cicadiloop,} \skvrobustdef*\skv@cicadiloop[#1]#2#3\fi#4{% @@ -1306,7 +1377,7 @@ % % \lpsdeclarelistnormalizer<normalizer.cmd>{<parser>} % -% Eg, +% Example: % % \lpsdeclarelistnormalizer\lpscommanormalize{,} % @@ -1314,7 +1385,7 @@ % \skvrobustdef*\lpsdeclarelistnormalizer#1#2{% \skvifescapedTF{#1}{}{% - \skv@err{Token \detokenize{#1} isn't escaped}\@ehd + \skv@err{Token \detokenize{#1} isn't escaped}\skv@ehd }% \def\reserved@a{\lps@declarelistnormalizer{#1}}% \expandafter\reserved@a\expandafter{\string#2}% @@ -1355,14 +1426,16 @@ \lpsdeclarelistnormalizer\lpsslashnormalize{/} % Declare an expandable csv list parser. No premature stopping of the loop -% is possible by this scheme. To use, first do +% is possible by this scheme. To use this scheme, first do % % \lpsdeclareexpandablelistparser<processor.cmd><processor.func>{<parser>} -% \def<processor.function>{<1-parameter callback>} +% \def<processor.func>{<1-parameter callback>} % % and then call % -% <processor.cmd><list> or <processor.cmd>*<listcmd>. +% <processor.cmd><list> or <processor.cmd>*<listcmd> +% +% <list> or <listcmd> will be normalized before being parsed. % % Example: % @@ -1399,38 +1472,21 @@ }% }% } - -\skvrobustdef*\lpsAtBeginEnvironment#1{% - \skvaftercs\skvappendtomacro{lps@atbegin@#1@hook}% -} -\skvrobustdef*\lpsAtEndEnvironment#1{% - \skvaftercs\skvappendtomacro{lps@atend@#1@hook}% -} - -\skvpatchcmd\begin - {\csname#1\endcsname} - {\skvcsuse{lps@atbegin@#1@hook}\csname#1\endcsname} - {} - {\skv@err{Patching '\string\begin' failed!\MessageBreak - '\string\lpsAtBeginEnvironment' will not work\@gobble}\@ehd - } - -\skvpatchcmd\end - {\csname end#1\endcsname} - {\skvcsuse{lps@atend@#1@hook}\csname end#1\endcsname} - {} - {\skv@err{Patching '\string\end' failed!\MessageBreak - '\string\lpsAtEndEnvironment' will not work\@gobble}\@ehd - } - -% Without the following patch, drawing intructions like +% Unfortunately, without the following patch, drawing instructions like +% +% \draw[blue] (p) \newforeach \p in {1,...,8}{...}; +% +% will not work, because of the way TikZ hardwires \foreach for this type +% of task (ie, when \draw precedes \newforeach or \foreachfox). The fact +% here is that in this case, both \newforeach and \foreachfox can't work +% but leave everything for \foreach. This can be a problem when \newforeach +% or \foreachfox is called to avoid a known bug in \foreach, such as at % -% \draw[blue] (p) \newforeach \p in {1,...,8}{...}; +% <http://tex.stackexchange.com/questions/79586/foreach-has-a-problem% +% -with-initially-argument-in-remember-part/79644#79644> % -% will not work, because of the way tikZ hardwires \foreach -% for this type of task. % -\lpsAtBeginEnvironment{tikzpicture}{% +\skvAtBeginEnvironment{tikzpicture}{% \def\tikz@handle@more{% \ifx\@let@token a\let\@next=\tikz@arcA\else \ifx\@let@token e\let\@next=\tikz@e@char\else |