<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
% This is file 'skeyval-for.tex', version 1.3, 2013/05/15.                 %
%                                                                          %
% This package and accompanying files may be distributed and/or            %
% modified under the conditions of the LaTeX Project Public License,       %
% either version 1.3 of this license or any later version. The latest      %
% version of this license is in http://www.latex-project.org/lppl.txt      %
% and version 1.3 or later is part of all distributions of LaTeX           %
% version 2005/12/01 or later.                                             %
%                                                                          %
% The LPPL maintenance status of this software is 'author-maintained'.     %
%                                                                          %
% This software is provided 'as it is', without warranty of any kind,      %
% either expressed or implied, including, but not limited to, the          %
% implied warranties of merchantability and fitness for a particular       %
% purpose.                                                                 %
%                                                                          %
% The following files constitute the skeyval bundle and must be            %
% distributed as a whole:                                                  %
%                                                                          %
%  README, skeyval.sty, skeyval-core.tex, skeyval-for.tex,                 %
%  skeyval-view.sty, skeyval-ltxpatch.sty, skeyval-ltxcmds.tex,            %
%  skeyval-pstkey.sty, skeyval-pstkey.tex, skeyval-testclass.cls,          %
%  skeyval-testpkg.sty, skeyval-pokayoke1, skeyval-pokayoke2,              %
%  skeyval-view-pokayoke1.                                                 %
%                                                                          %
% Copyright (c) 2010-2013 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\&gt;\do\&lt;\do\!\do\*\do\+\do\-\do\^\do\_\do\&amp;\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`\&lt;=12 \catcode`\&gt;=12 \catcode`\!=12 \catcode`\.=12
\catcode`\^=07 \catcode`\_=08 \catcode`\&amp;=04 \catcode`\$=03
\catcode`\~=13 \catcode`\%=14 \catcode`\'=12 \catcode`\"=12

\csname skeyval-for-loaded\endcsname
\expandafter\let\csname skeyval-for-loaded\endcsname\endinput

\ifx\ProvidesFile\@undefined
  \message{File 'skeyval-for.tex' 2013/05/15 v1.3
    Loops for skeyval package (AM)}
\else
  \ProvidesFile{skeyval-for.tex}
    [2013/05/15 v1.3 Loops for skeyval package (AM)]
  \@addtofilelist{skeyval-for.tex}
\fi

\skvrobustdef*\skv@nostackerr{%
  \skv@err{You've called an empty stack}\skv@ehd
}
% \skvsavestate&lt;base-fn&gt;{&lt;fn-list&gt;}&lt;counter-number&gt;
%
% See file skeyval-core.tex for \skvpushfunctions and \skvpopfunctions.
%
\skvrobustdef*\skvsavestate#1#2#3{%
  \skvgadvanceno#3\@ne
  \begingroup
  \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}}}%
  \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
}
% \skvrestorestate&lt;base-fn&gt;&lt;counter-number&gt;
\skvrobustdef*\skvrestorestate#1#2{%
  \begingroup
  \let\nostack\skv@nostackerr
  \edef\skv@elt{\skvnoexpandcs{\skvremovescape#1@skv@stack}}%
  \expandafter\ifx\skv@elt\relax
    \skv@err{Stack of '\noexpand#1' is undefined}\skv@ehd
  \fi
  \edef\skv@prova{\skvexpandtwice\skv@elt}%
  \edef\skv@provb##1##{\endgroup##1\gdef\skvexpandonce\skv@elt}%
  \expandafter\skv@provb\skv@prova
  \skvgadvanceno#2\m@ne
}
\skvnewregisters\bool{%
  \ifbreakallforeachloops,\ifskvbreakloop,\ifforeachlastitem,
  \ifskvprocessempty,\ifskv@foreach@swa,\ifskv@foreach@swb,
  \ifskv@foreach@parenthesis,\ifskv@useemptylist,\ifskv@inforeach,
}
\skvnewlet\skvbreakloop\skvbreaklooptrue
\skvnewlet\breaknewforeach\skvbreaklooptrue
% \breakallforeachloops will break all current loops (inner and outer):
\skvnewdef*\breakallforeachloops{%
  \skvbreaklooptrue\breakallforeachloopstrue
}

\skvnewnumbers[skv@]{csvdepth,dolistdepth}
%
% \skvdolist{&lt;parser&gt;}{&lt;list&gt;}&lt;holdercmd&gt;{&lt;callback&gt;}
% \skvdolist*{&lt;parser&gt;}{&lt;listcmd&gt;}&lt;holdercmd&gt;{&lt;callback&gt;}
% \skvparselist{&lt;parser&gt;}{&lt;list&gt;}&lt;holdercmd&gt;{&lt;callback&gt;}
% \skvparselist*{&lt;parser&gt;}{&lt;listcmd&gt;}&lt;holdercmd&gt;{&lt;callback&gt;}
% \skvprocesslist{&lt;parser&gt;}{&lt;list&gt;}&lt;holdercmd&gt;{&lt;callback&gt;}
% \skvprocesslist*{&lt;parser&gt;}{&lt;listcmd&gt;}&lt;holdercmd&gt;{&lt;callback&gt;}
%
% 1. These macros can process both csv and tsv/nsv lists. Use empty
%    &lt;parser&gt; for tsv lists.
% 2. These macros can be nested to any depth, with different parsers
%    on each level.
% 3. \skvdolist and \skvparselist will not process an empty list, but
%    \skvprocesslist will do so.
% 4. For comma lists, \skvcommaloop and \skvcommaparse are faster.
%    See later.
% 5. For processing kv lists, use \skvparsekvlist.
% 6. The preservation of outer braces isn't a priority in this loop.
%
\skvrobustdef*\skvdolist{\skv@useemptylistfalse\skv@testst\skv@dolist}
\skvrobustdef*\skv@dolist#1#2#3#4{%
  \skv@usetempst{#2}#3%
  % \skvlistcount is used by listkeys.
  \skvsavestate\skvdolist{%
    \do\skv@dolist@callback
    \do\skv@dolist@a\do\skvlistcount\do\ifskv@useemptylist
  }\skv@dolistdepth
  \edef\skv@dolist@callback{\unexpanded{#4}}%
  \def\skvlistcount{0}%
  \def\skv@dolist@a##1##2#1{%
    \skvifstrcmpTF{##2}{\skv@dolist@nil}{%
      % To allow nesting of loop:
      \skvbreakloopfalse
    }{%
      \edef##1{\unexpanded{##2}}%
      \edef\skvlistcount{\the\numexpr\skvlistcount+1}%
      \skv@dolist@callback\relax
      \ifskvbreakloop
        \skvbreakloopfalse
        \begingroup
        \def\skv@dolist@a####1####2\skv@dolist@nil#1{%
          \endgroup
          \edef\skvremainder{\unexpanded{####2}}%
        }%
      \fi
      \skv@dolist@a{##1}%
    }%
  }%
  \ifskv@useemptylist
    \def\reserved@a##1##2##3{##3}%
  \else
    \let\reserved@a\skvifemptyTF
  \fi
  \reserved@a#3{}{%
    \expandafter\skv@dolist@a\expandafter#3#3#1\skv@dolist@nil#1%
  }%
  \skvrestorestate\skvdolist\skv@dolistdepth
}
% First normalize the list before parsing.
\skvrobustdef*\skvparselist{\skv@useemptylistfalse\skv@testst\skv@parselist}
\skvrobustdef*\skvprocesslist{\skv@useemptylisttrue\skv@testst\skv@parselist}
\skvrobustdef*\skv@parselist#1#2#3{%
  \skv@usetempst{#2}#3%
  \skvcsvnormalize[#1]#3%
  \skv@tempsttrue
  \skv@dolist{#1}#3#3%
}

\skvnewlet\foreachlistbreaker\relax
\skvnewlet\foreachlistpauser\relax
\skvnewdef*\skv@listbreakertoks{\foreachlistbreaker}
\skvnewdef*\skv@listpausertoks{\foreachlistpauser}
\skvnewlet\skvprocessempty\skvprocessemptytrue

% Reversing tokens:
\skvnewdef*\skvreverse#1{\skv@reverse#1\skv@reverse@stop}
\skvnewdef*\skv@reverse#1#2\skv@reverse@stop{%
  \if\relax\detokenize{#2}\relax\skv@reverse@stop\fi
  \skv@reverse#2\skv@reverse@stop\skvreversedo{#1}%
}
\skvnewdef*\skv@reverse@stop#1\skv@reverse@stop{\fi}
\let\skvreversedo\@iden

\skvrobustdef*\skv@removetrailingparser#1#2{%
  \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}%
  }{}%
}

% \skvrecurse&lt;body&gt;\while&lt;\if...&gt;\fi
%
% On entry, the condition is checked before the body is executed.
%
% \@tempcnta\z@
% \skvrecurse{
%   \advance\@tempcnta\@ne
%   \@tempcntb\z@
%   \skvrecurse
%     \advance\@tempcntb\@ne
%     \typeout{Doing \the\@tempcnta,\the\@tempcntb}
%   \while
%     \ifnum\@tempcntb&lt;3
%   \fi
%  }
% \while
%   \ifnum\@tempcnta&lt;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&gt;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}}%
}

% A version of LaTeX's \@tfor that can parse undoubled parameter
% characters and terminate the loop by using \skvbreakloop.
%
% \skvtfor&lt;holder.cmd&gt;:={&lt;list&gt;}\do{&lt;callback&gt;}
% \skvtfor*&lt;holder.cmd&gt;:={&lt;listcmd&gt;}\do{&lt;callback&gt;}
%
% Example:
%
%  \skvnewregister\count{\nr}
%  \skvtfor\x:=a \ifx {\def\x#1{#1}} \fi\do{%
%    \nr\z@
%    \skvtfor\y:=12345\do{%
%      \typeout{Doing: \detokenize\expandafter{\x}--\y}%
%      \advance\nr\@ne
%      \ifnum\nr&gt;\tw@\skvbreakloop\fi
%    }
%  }
%
\skvnewdef*\skv@tfor@nil{\skv@tfor@nil}
\skvrobustdef*\skvtfor{\skv@testst\skv@tfor}
\skvrobustdef*\skv@tfor#1:={\skv@tf@r#1 }
\skvrobustdef\skv@tf@r#1#2\do#3{%
  \edef#1{\skvtrimspace{#2}}%
  \edef#1{\skvifdefboolTF{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}}%
  \skvifxTF#3\skv@tfor@nil{%
    \skvbreakloopfalse
  }{%
    #4\relax
    \ifskvbreakloop
      \skvbreakloopfalse
      \begingroup
      \def\skv@tforloop##1\skv@tfor@nil\skv@tfor##2##3{%
        \endgroup
        \edef\skvremainder{\unexpanded{##1}}%
      }%
    \fi
    \skv@tforloop#2\skv@tfor#3{#4}%
  }%
}

%+++++++++++++++      Non-expandable comma loops       ++++++++++++++%%
%
% 1. These follow from \skvdolist and \skvparselist, but they are
%    specialized for comma lists and they are faster, since they don't
%    stack any state.
% 2. There is no fear of parameter characters in &lt;callback&gt; being mixed
%    with those of \skv@commaloop@picknext.
% 3. These loops can be nested to any depth.
% 4. The preservation of outer braces isn't a priority in these loops.
%
% \skvcommaloop{&lt;list&gt;}&lt;holder-cmd&gt;{&lt;callback&gt;}
% \skvcommaloop*{&lt;listcmd&gt;}&lt;holder-cmd&gt;{&lt;callback&gt;}
%
% Example:
%
%   \skvcommaloop{x#1,y#1}\tempa{\edef\xx#1{#1\tempa}}
%
\skvrobustdef*\skvcommaloop{\skv@testst\skv@commaloop}
\skvrobustdef\skv@commaloop#1#2#3{%
  \skv@usetempst{#1}#2%
  % Don't put \skvcsvnormalize#2 here. Use \skvcommaparse instead.
  % Some callers of \skvcommaloop already have their lists normalized.
  \skvifxTF#2\@empty{}{%
    \skvbreakloopfalse
    \skvexpandnext{\skv@commaloop@picknext#2{#3}}#2,\skv@commaloop@nil,%
  }%
}
\skvrobustdef\skv@commaloop@picknext#1#2#3,{%
  \skvifstrcmpTF{#3}{\skv@commaloop@nil}{%
    \skvbreakloopfalse
  }{%
    \edef#1{\unexpanded{#3}}%
    #2\relax
    \ifskvbreakloop
      \skvbreakloopfalse
      \begingroup
      \long\def\skv@commaloop@picknext##1##2##3\skv@commaloop@nil,{%
        \endgroup
        \edef\skvremainder{\unexpanded{##3}}%
      }%
    \fi
    \skv@commaloop@picknext#1{#2}%
  }%
}
%
% \skvecommaloop{&lt;list&gt;}&lt;cmd&gt;{&lt;callback&gt;}
% \skvecommaloop*{&lt;listcmd&gt;}&lt;cmd&gt;{&lt;callback&gt;}
%
% \skvecommaloop is as \skvcommaloop but will execute &lt;callback&gt;
% once when &lt;list&gt; is empty. This is needed for processing empty
% families.
%
\skvrobustdef\skvecommaloop{\skv@testst\skv@ecommaloop}
\skvrobustdef\skv@ecommaloop#1#2#3{%
  \edef#2{\unexpanded{\skv@commaloop@picknext#2{#3}}}%
  \ifskv@tempst\expandafter\expandafter\fi#2#1,\skv@commaloop@nil,%
}
%
% \skvcommaparse{&lt;list&gt;}&lt;cmd&gt;{&lt;callback&gt;}
% \skvcommaparse*{&lt;listcmd&gt;}&lt;cmd&gt;{&lt;callback&gt;}
%
% \skvcommaparse is as \skvcommaloop but will first normalize &lt;list&gt;
% using \skvcsvnormalize.
%
\skvrobustdef*\skvcommaparse{\skv@testst\skv@commaparse}
\skvrobustdef\skv@commaparse#1#2#3{%
  \skv@usetempst{#1}#2%
  \skvcsvnormalize#2%
  \skvcommaloop*#2#2{#3}%
}
% \skvkvparse{&lt;list&gt;}&lt;cmd&gt;{&lt;callback&gt;}
% \skvkvparse*{&lt;listcmd&gt;}&lt;cmd&gt;{&lt;callback&gt;}
%
% 1. \skvkvparse is as \skvcommaloop but will first normalize &lt;list&gt; using
%    \skvkvnormalize.
% 2. It is meant for processing key-value lists.
%
\skvrobustdef*\skvkvparse{\skv@testst\skv@kvparse}
\skvnewlet\skvparsekvlist\skvkvparse
\skvrobustdef\skv@kvparse#1#2#3{%
  \skv@usetempst{#1}#2%
  \skvkvnormalize#2%
  \skvcommaloop*#2#2{#3}%
}
% \skvcountelements[&lt;parser&gt;]{&lt;list&gt;}{&lt;return.cmd&gt;}
% \skvcountelements*[&lt;parser&gt;]{&lt;listcmd&gt;}{&lt;return.cmd&gt;}
\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 &lt;nr&gt;.
% \skvifelementcount[&lt;parser&gt;]{&lt;list&gt;}{&lt;nr&gt;}{&lt;true&gt;}{&lt;false&gt;}
% \skvifelementcount*[&lt;parser&gt;]{&lt;listcmd&gt;}{&lt;nr&gt;}{&lt;true&gt;}{&lt;false&gt;}
\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[&lt;parser&gt;]&lt;listcmd&gt;
\skvrobustdef*\skv@foreach@normalize{\skv@testopt\skv@foreach@norm@lize,}
\skvrobustdef*\skv@foreach@norm@lize[#1]#2{%
  \skvxifntypeTF{\detokenize{#1}}\skvcsvnormalize\skvmacnormalize[#1]#2%
}

% \newforeach[&lt;options&gt;] &lt;holders&gt; {&lt;list&gt;} {&lt;callback&gt;}
% \newforeach*[&lt;options&gt;] &lt;holders&gt; {&lt;listcmd&gt;} {&lt;callback&gt;}
% \newforeach[&lt;options&gt;] &lt;holders&gt; in {&lt;list&gt;} do {&lt;callback&gt;}
% \newforeach*[&lt;options&gt;] &lt;holders&gt; in {&lt;listcmd&gt;} do {&lt;callback&gt;}
% \newforeach[&lt;options&gt;] &lt;holders&gt; in {&lt;list&gt;} &lt;callback&gt; ;
% \newforeach*[&lt;options&gt;] &lt;holders&gt; in {&lt;listcmd&gt;} &lt;callback&gt; ;
%
% 1. &lt;callback&gt; is the code that will be executed for each element
%    of the list. It will refer to the holder macros &lt;holders&gt;.
%
% 3. Elements of the form (a,b) and [a,b] are grabbed together.
%
% 4. Use \breaknewforeach to break out of the loop prematurely.
%
% 5. \newforeach can be nested.
%
% 6. The star (*) variant of \newforeach is equivalent to using the
%    key 'list is a macro' (or *) in &lt;options&gt;.
%
% \skv@foreach@holderdepth must be different from \foreachnestdepth,
% to avoid confusing two different stacks.
\skvnewnumbers{foreachnestdepth,skv@foreach@holderdepth,%
  skv@foreach@nra,skv@warnsubparser}
% \newforeach will not accept \skvifstreq or \skvifstrcmpTF because
% they don't start with '\if'. So we introduce \ifforeachstrcmp:
\skvnewlet\ifforeachstrcmp\skvifstreq
\skvnewdef*\skv@foreach@onlyinitially{}
\skvrobustdef*\skvforeachonlyinitially#1{%
  \edef\skv@foreach@onlyinitially{%
    \skvexpandonce\skv@foreach@onlyinitially
    \unexpanded{#1}%
  }%
}
% \skv@foreach@addtocallback{&lt;pre.or.post&gt;}{&lt;code.to.add&gt;}
\skvrobustdef*\skv@foreach@addtocallback#1#2{%
  \skvcsedef{skv@foreach@#1callback}{%
    \skvifcsdefFT{skv@foreach@#1callback}{}{%
      \skvexpandcsonce{skv@foreach@#1callback}%
    }%
    % No \unexpanded for #2 here, since #2 is to be expanded:
    #2%
  }%
}

\skvnewlet\skv@foreach@codemark\relax
\skvrobustdef*\skv@foreach@addtohook#1#2#3{%
  \begingroup
  \skvifdefTF#2{}{\def#2{}}%
  \edef\x{\detokenize{\skv@foreach@codemark#3\skv@foreach@codemark}}%
  \skvxifinTF\x{\skvoxdetok#2}{}{%
    \edef#2{%
      \skvifstrcmpTF{#1}{pre}{%
        \skv@foreach@codemark\unexpanded{#3}\skv@foreach@codemark
        \skvexpandonce{#2}%
      }{%
        \skvexpandonce{#2}%
        \skv@foreach@codemark\unexpanded{#3}\skv@foreach@codemark
      }%
    }%
  }%
  \skvaftergroupdef#2\endgroup
}

% \prependtobeginforeach[&lt;depths&gt;]{&lt;code&gt;}
\skvrobustdef*\prependtobeginforeach{%
  \skv@testopt{\skv@atbeginforeach{pre}}{}%
}
% \appendtobeginforeach[&lt;depths&gt;]{&lt;code&gt;}
\skvrobustdef*\appendtobeginforeach{%
  \skv@testopt{\skv@atbeginforeach{app}}{}%
}
\skvnewlet\atbeginforeach\appendtobeginforeach
\skvrobustdef*\skv@atbeginforeach#1[#2]#3{%
  \skvifblankTF{#2}{%
    \skvaftercsname{\skv@foreach@addtohook{#1}}%
      {skv@foreach@atbeginhook@\skvrom\@ne}{#3}%
  }{%
    \skvcommaloop{#2}\skv@tempa{%
      \skvaftercsname{\skv@foreach@addtohook{#1}}%
        {skv@foreach@atbeginhook@\skvrom\number\skv@tempa}{#3}%
    }%
  }%
}
% \prependtoendforeach[&lt;depths&gt;]{&lt;code&gt;}
\skvrobustdef*\prependtoendforeach{%
  \skv@testopt{\skv@atendforeach{pre}}{}%
}
% \appendtoendforeach[&lt;depths&gt;]{&lt;code&gt;}
\skvrobustdef*\appendtoendforeach{%
  \skv@testopt{\skv@atendforeach{app}}{}%
}
\skvnewlet\atendforeach\appendtoendforeach
\skvrobustdef*\skv@atendforeach#1[#2]#3{%
  \skvifblankTF{#2}{%
    \skvaftercsname{\skv@foreach@addtohook{#1}}%
      {skv@foreach@atendhook@\skvrom\@ne}{#3}%
  }{%
    \skvcommaloop{#2}\skv@tempa{%
      \skvaftercsname{\skv@foreach@addtohook{#1}}%
        {skv@foreach@atendhook@\skvrom\number\skv@tempa}{#3}%
    }%
  }%
}
% \atbeginforeachondepth{&lt;depths&gt;}{&lt;code&gt;}
\skvrobustdef*\atbeginforeachondepth#1#2{%
  \appendtobeginforeach[#1]{#2}%
}
% \atendforeachondepth{&lt;depths&gt;}{&lt;code&gt;}
\skvrobustdef*\atendforeachondepth#1#2{%
  \appendtoendforeach[#1]{#2}%
}

% \skv@foreach@fi@toks must use \detokenize. Don't change to \string!
\skvnewedef*\skv@foreach@fi@toks{\detokenize{\fi}}
\skvnewedef*\skv@foreach@if@toks{\string\if}

% \skv@foreach@ifacceptkv and \skv@foreach@maketester must come
% before the initialization of keys:
\skvrobustdef*\skv@foreach@ifacceptkv#1#2{%
  \def\next{}%
  \ifskvindef\else
    \edef\skv@prova{\unexpanded{#1}}%
    \ifnum0&gt;\numexpr0\ifx\skv@prova\@empty-1\else
      \ifx\skv@prova\@nnil-1\else+0\fi\fi\relax\relax
      \skv@err{Invalid syntax '\detokenize{#1}'}\skv@ehd
    \else
      \edef\next{\unexpanded{#2}}%
    \fi
  \fi
  \next
}
\skvrobustdef*\skv@foreach@ifholderisonecmd#1#2#3{%
  \skvifntypeTF{#2}{%
    \skvifescapedTF{#2}{%
      #3%
    }{%
      \skv@err{Value of key '#1' must
      \MessageBreak be escaped: the holder macro
      \MessageBreak to be evaluated}\skv@ehd
    }%
  }{%
    \skv@err{Value of key '#1' must
      \MessageBreak be only one token: the holder
      \MessageBreak macro to be evaluated}\skv@ehd
  }%
}
% \skv@foreach@maketester{&lt;cond&gt;}&lt;cond.tester.cmd&gt;{&lt;flag&gt;}
%
% 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. &lt;flag&gt; is either 0 or 1, signifying whether or not the condition
%    should be entered in postcallback. This is because
%    \skv@foreach@maketester is called (by key 'loop stopper') for
%    formating the premature exit condition and (in
%    \skv@foreach@parsecountin and \skv@foreachfox@parsecountin) for the
%    condition for counting an item of the list. In the latter case,
%    there is no need to enter the formated
%    condition in the postcallback, since it it is entered in the
%    'afterprecallback' or (in the case of \foreachfox) in 'precallback'.
%
%    Examples: \ifnum\x&gt;10\fi, \ifx\x\cmd\fi.
%
\skvrobustdef*\skv@foreach@maketester#1#2#3{%
  % Make '#1' innocent in a macro, in case it contains parameter
  % characters. \skv@prova will appear only in the error message.
  \begingroup
  \edef\skv@prova{\detokenize{#1}}%
  \skvifblankTF{#1}{%
    \skv@err{A blank conditional has been given in
      \MessageBreak\string\newforeach or a similar command}\skv@ehd
  }{%
    \skvxifinTF{\skv@foreach@fi@toks\relax}{\detokenize{#1}\relax}{%
      \skvxifinTF{\relax\skv@foreach@if@toks}{\relax\detokenize{#1}}{%
        \edef#2{\noexpand\skvifconditionTF\unexpanded{#1}}%
        \ifnum#3=\@ne
          \skv@foreach@addtocallback{post}{%
            \unexpanded{\skvifconditionTF#1}{\noexpand\skvbreakloop}{}%
          }%
        \fi
      }{%
        \skv@err{Invalid conditional '\skv@prova'}
          {Invalid, possibly unbalanced, conditional '\skv@prova'}%
      }%
    }{%
      \skv@err{Invalid conditional '\skv@prova'}\skv@ehd
    }%
  }%
  \skvexpanded{\endgroup
    \skvcmdexit#2%
    \ifnum#3=\@ne
      \skvcmdexit\skv@foreach@postcallback
    \fi
  }%
}
\skvquickkeys.define{skeyval/foreach}{%
  .exec/
    \def\skv@foreach@parser{,}
    \def\skv@foreach@subparser{/}
  ;
  parser/{,}/
    \edef\skv@foreach@parser{\unexpanded{#1}}
    \skvstripouterbraces{2}\skv@foreach@parser
    \skvxifntypeTF{\detokenize{#1}}{%
      \begingroup
      % It is assumed that every n-type parser and subparser
      % must have catcode 12:
      \skvexpandnext{\catcode`}\skv@foreach@parser=12\relax
      \skvrescan\skv@foreach@parser
      \skvaftergroupdef\skv@foreach@parser\endgroup
    }{}
  ;
  subparser/{/}/
    \edef\skv@foreach@subparser{\unexpanded{#1}}
    \skvstripouterbraces{2}\skv@foreach@subparser
    \skvxifntypeTF{\detokenize{#1}}{
      \begingroup
      \skvexpandnext{\catcode`}\skv@foreach@subparser=12\relax
      \skvrescan\skv@foreach@subparser
      \skvaftergroupdef\skv@foreach@subparser\endgroup
    }{}
  ;
  terminator,callback terminator/{;}/
    \edef\skv@foreach@terminator{\unexpanded{#1}}%
    \skvstripouterbraces{2}\skv@foreach@terminator
  ;
  % process up to = &lt;nr&gt;
  % Maximum number of items to process:
  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
  ;
  process empty list/true/
    \edef\skv@foreach@processempty{0\skvifstrcmpTF{true}{#1}01}%
    /true,false
  ;
  % 'break=&lt;condition&gt;'
  % Break list processing when &lt;condition&gt; is satisfied. &lt;condition&gt; must
  % be a balanced plain TeX conditional. Eg, 'exit when={\ifnum\x=20\fi}'.
  % Notice the use of outer braces in '{\ifnum\x=20\fi}'. This avoids
  % conflicting the two equality signs: for the key-value and for number
  % testing.
  .exec/\let\skv@foreach@exittester\@secondoftwo;
  break,loop stopper,exit when/\if01\fi/
    \edef\skv@tempa{\unexpanded{#1}}%
    \skvstripouterbraces{2}\skv@tempa
    \skvexpbracenext\skv@foreach@maketester\skv@tempa
      \skv@foreach@exittester\@ne
  ;
  % Java-type of continue: If the user wants to ignore the callback for
  % some items, he can instantiate the key 'condition=&lt;condition&gt;'.
  % &lt;condition&gt; must be a balanced plain TeX conditional. Eg,
  % continue={\ifnum\x=20\fi}.
  .exec/\let\skv@foreach@continuetester\@secondoftwo;
  continue,ignore callback/\if01\fi/
    \edef\skv@tempa{\unexpanded{#1}}%
    \skvstripouterbraces{2}\skv@tempa
    \skvexpbracenext\skv@foreach@maketester\skv@tempa
      \skv@foreach@continuetester\skvz@
  ;
  % Eg, 'evaluate = \x as \z using \numexpr\x*2'. 'as' and 'using', and the
  % tokens after them, can be missing, but the formula must be complete.
  evaluate/\@nil/
    \skv@foreach@ifacceptkv{#1}{%
      \skv@foreach@parseevaluate{#1}%
    }%
  ;
  % The evaluator \numexpr will invariably be used internally for this key.
  % 'as' and 'using' are illegal here. This is only a shortcut for 'evaluate'.
  evaluate num,evaluate number/\@nil/
    \skv@foreach@ifacceptkv{#1}{%
      \skv@foreach@ifholderisonecmd{evaluate number}{#1}{%
        \skv@foreach@parseevaluate{#1as#1using\numexpr#1}%
      }%
    }%
  ;
  % The evaluator \dimexpr will invariably be used internally for this key.
  % 'as' and 'using' are illegal here. This is only a shortcut for 'evaluate'.
  evaluate dim,evaluate dimension/\@nil/
    \skv@foreach@ifacceptkv{#1}{%
      \skv@foreach@ifholderisonecmd{evaluate dimension}{#1}{%
        \skv@foreach@parseevaluate{#1as#1using\dimexpr#1}%
      }%
    }%
  ;
  % Eg, 'expand=\x'.
  % Fully expand holder macro. This is equivalent to, eg, edef\x{\x}.
  % 'as' and 'using' are illegal here. This is only a shortcut for 'evaluate'.
  expand,expanded/\@nil/
    \skv@foreach@ifacceptkv{#1}{%
      \skv@foreach@ifholderisonecmd{expand}{#1}{%
        \skv@foreach@parseevaluate{#1as#1using#1}%
      }%
    }%
  ;
  % Eg, 'pgf parse = \x as \xe using \x*3'. 'as' and 'using', and the
  % tokens after them, can be present or missing.
  % \pgfmathparse is always used for this key.
  pgf evaluate,pgf parse,pgfmath parse/\@nil/
    \skv@foreach@ifacceptkv{#1}{%
      \skv@foreach@parsepgfmathparse{#1}%
    }%
  ;
  % count in = \y all \x satisfying &lt;condition&gt; initially &lt;value&gt;
  % Eg,
  %    count in = \p all \x satisfying \ifnum\x&gt;4\fi, or
  %    count in = \p all \x satisfying \skvifnumTF\x&gt;4
  % The counting is not additive, meaning that the counter is initialized
  % to zero on each depth.
  count in,count/\@nil/
    \skv@foreach@ifacceptkv{#1}{%
      \skv@foreach@parsecountin{#1}%
    }%
  ;
  % Eg, 'remember=\x as \y initially A':
  remember/\@nil/
    \skv@foreach@ifacceptkv{#1}{%
      \skv@foreach@parseremember{#1}%
    }%
  ;
  % Eg, 'recall=\x initially A'.
  % 'recall' is as 'remember', but will save the value of the holder macro
  % in \&lt;foreachlast&gt;&lt;holder&gt;. 'as' is invalid/illegal here, since a
  % retainer macro is built internally:
  retain,recall,call up/\@nil/
    \skv@foreach@ifacceptkv{#1}{%
      \skv@foreach@parserecall{#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
    }%
  ;
  list breaker/\foreachlistbreaker/
    \edef\skv@prova{\unexpanded{#1}}%
    \ifx\skv@prova\@empty
      \skv@err{Invalid empty value for key 'list breaker'}\skv@ehd
    \else
      \let\skv@listbreakertoks\skv@prova
    \fi
  ;
  list pauser/\foreachlistpauser/
    \edef\skv@prova{\unexpanded{#1}}%
    \ifx\skv@prova\@empty
      \skv@err{Invalid empty value for key 'list pauser'}\skv@ehd
    \else
      \let\skv@listpausertoks\skv@prova
    \fi
  ;
  % Remember outside the loop the holder values. Of course, this
  % means remembering only the latest values.
  recover holder values,recover holder values after loop/true/
    \edef\skv@foreach@recoverholders{0\skvifstrcmpTF{true}{#1}01}%
    /true,false
  ;
  % This default value of 'link' is required by \skvautocompletelist:
  .exec code/\def\skv@foreach@link{\@nil};
  link/\@nil/
    \edef\skv@prova{\unexpanded{#1}}%
    \ifcase0%
      \ifx\skv@prova\@empty 1\fi
      \ifx\skv@prova\@nnil 1\fi\relax
      \edef\skv@foreach@link{\unexpanded{#1}}%
      \skvstripouterbraces{2}\skv@foreach@link
    \fi
  ;
  grow/\@nil/
    \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
  ;
  .exec/
    \def\skv@foreach@growleft{01}
    \def\skv@foreach@growright{01}
  ;
  grow left/true/
    \edef\skv@foreach@growleft{0\skvifstrcmpTF{true}{#1}01}
    /true,false
  ;
  grow right/true/
    \edef\skv@foreach@growright{0\skvifstrcmpTF{true}{#1}01}
    /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\skvifstrcmpTF{true}{#1}01}
    /true,false
  ;
  keep high decimals,keep only high decimals/true/
    \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,transfer macro values/true/
    \edef\skv@foreach@inherit{0\skvifstrcmpTF{true}{#1}01}
    /true,false
  ;
  expand before fill,expand list before fill/true/
    \edef\skv@foreach@expandbeforefill{0\skvifstrcmpTF{true}{#1}01}
    /true,false
  ;
  expand list once,x1,list is a macro,macro list/true/
    \edef\skv@foreach@expandlistonce{0\skvifstrcmpTF{true}{#1}01}%
    /true,false
  ;
  expand list twice,x2/true/
    \edef\skv@foreach@expandlisttwice{0\skvifstrcmpTF{true}{#1}01}%
    /true,false
  ;
  % Don't use 'expand' for this key, to avoid confusing it with
  % the 'expand' for holder macros:
  expand list,fully expand list,expand list fully,xx/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
  ;
  % 'hide parameters' can be used to avoid doubling the parameter
  % characters in the callback.
  hide parameters/true/
    \edef\skv@foreach@hideparameters{0\skvifstrcmpTF{true}{#1}01}
    /true,false
  ;
}

% The following keys don't need presetting. The user must supply
% values when they are called. In internal loops, their values will
% have to be revised from those of the outer loop.
%
%    link,evaluate,,evaluate num,evaluate dim,expand,count in,
%    process up to,grow
%
\skvquickkeys.preset{skeyval/foreach}{%
  parser,subparser,loop stopper,callback terminator,process up to,
  process empty list=false,item counter,list breaker,list pauser,
  recover holder values=false,grow left=false,grow right=false,
  keep decimals=true,keep high decimals=false,inherit=false,
  expand before fill=false,reverse list=false,expand list once=false,
  expand list twice=false,expand list fully=false,hide parameters=false
}

\skvnewdef*\skv@foreach@kvlist{}
% \setupforeach{&lt;kvlist&gt;}
\skvrobustdef*\setupforeach#1{%
  \skvifblankTF{#1}{}{%
    \skvaddtolist\skv@foreach@kvlist{#1}%
  }%
}
\skvrobustdef*\skv@foreach@setkeys#1{%
  \def\reserved@a{\skvquickkeys.set{skeyval/foreach}}%
  \expandafter\reserved@a\expandafter{\skv@foreach@kvlist,#1}%
}

% evaluate=&lt;holder.macro&gt; as &lt;child.macro&gt; using &lt;formula&gt;
%
% 1. Evaluation is done with \edef unless \pgfmathparse is present
%    in &lt;formula&gt; or key 'pgf evaluate' is called.
%
% 2. &lt;formula&gt; must be a valid formula, eg,
%
%      \pgfmathparse\x*2
%      \pgfmathparse{exp(50)*\x*2+sin(.5*pi)*60}
%      \numexpr\x*2
%      \skvexpandonce\x
%
%    or simply
%
%    'evaluate \x as \x using &lt;empty&gt;'
%
%    The latter is equivalent to asking for full expansion. See also
%    the keys 'evaluate num', 'evaluate dim', and 'expand'.
%
% 3. This allows &lt;formula&gt; to be generic.
%
\skvrobustdef*\skv@foreach@parseevaluate#1{%
  \begingroup
  \def\skv@tempxifin##1##2{%
    \skvxifinTF{\detokenize{##1}}{\detokenize{##2}}%
  }%
  \skv@foreach@swafalse
  \def\skv@tempd{}%
  \def\skv@tempa##1as##2using##3\skv@nil{%
    \edef\skv@prova{\skvtrimspace{##1}}%
    \edef\skv@provb{\skvtrimspace{##2}}%
    \edef\skv@provc{\skvtrimspace{##3}}%
    \ifx\skv@prova\@empty
      \skv@err{Value of key 'evaluate' has no holder macro}\skv@ehd
    \else
      \expandafter\skvifescapedTF\expandafter{\skv@prova}{%
        \expandafter\skvifntypeTF\expandafter{\skv@prova}{}{%
          \skv@err{Value of key 'evaluate': more than 1
            \MessageBreak token \skvoxdetok\skv@prova.
            \MessageBreak I can't find holder macro}\skv@ehd
        }%
      }{%
        \skv@err{Value of key 'evaluate':
          \MessageBreak holder macro \skvoxdetok\skv@prova not escaped}\skv@ehd
      }%
    \fi
    \ifx\skv@provb\@empty
      \skv@err{Value of key 'evaluate' has no child macro}\skv@ehd
    \else
      \expandafter\skvifescapedTF\expandafter{\skv@provb}{%
        \expandafter\skvifntypeTF\expandafter{\skv@provb}{}{%
          \skv@err{Value of key 'evaluate': more than 1
            \MessageBreak token \skvoxdetok\skv@provb.
            \MessageBreak I can't find child macro}\skv@ehd
        }%
      }{%
        \skv@err{Value of key 'evaluate':
          \MessageBreak child \skvoxdetok\skv@provb not escaped}\skv@ehd
      }%
    \fi
    \ifx\skv@provc\@empty
      \skv@err{Value of key 'evaluate' has no formula or
        \MessageBreak holder macro to be expanded}\skv@ehd
    \fi
    \skv@tempxifin{\pgfmathparse}{##3}{%
      \def\skv@tempc####1\pgfmathparse####2\skv@nil{%
        \ifx\@nnil####1\@nnil
          \skv@foreach@swatrue
        \else
          \skv@err{Invalid token \detokenize{####1}
            \MessageBreak before \string\pgfmathparse}\skv@ehd
        \fi
      }%
      \skv@tempc##3\skv@nil
    }{%
      \skv@tempxifin{\numexpr}{##3}{%
        \def\skv@tempd{\relax}%
      }{%
        \skv@tempxifin{\dimexpr}{##3}{%
          \def\skv@tempd{\relax}%
        }{%
          \def\skv@tempd{}%
        }%
      }%
    }%
  }%
  \skv@tempxifin{using}{#1}{%
    \skv@tempxifin{as}{#1}{%
      % 'as' and 'using' are present: maybe there is a formula.
      \skv@foreach@swbtrue
      \skv@tempa#1\skv@nil
    }{%
      \skv@err{Value of key 'evaluate':
        \MessageBreak there is 'using', but no 'as'}\skv@ehd
    }%
  }{%
    % No formula given. Maybe the key is 'expand' or still 'evaluate'
    % but without formula.
    \skv@foreach@swbfalse
    \skv@tempxifin{as}{#1}{%
      \def\skv@tempb##1as##2##3\skv@nil{%
        \ifx\@nnil##1\@nnil
          \skv@err{Value of key 'evaluate' has no holder macro}\skv@ehd
        \else
          \ifx\@nnil##2%
            \skv@err{Value of key 'evaluate' has no child macro}\skv@ehd
          \else
            \skv@tempa##1as##2using##1\skv@nil
          \fi
        \fi
      }%
      \skv@tempb#1{\@nnil}\skv@nil
    }{%
      % No 'as' or 'using': #1 should be only the holder macro:
      \ifx\@nnil#1\@nnil
        \skv@err{Value of key 'evaluate' has no holder macro}\skv@ehd
      \else
        \skvifntypeTF{#1}{%
          % Expand the holder macro:
          \skv@tempa#1as#1using#1\skv@nil
        }{%
          \skv@err{Value of key 'evaluate': more than 1
            \MessageBreak token '\detokenize{#1}'.
            \MessageBreak I can't find holder macro}\skv@ehd
        }%
      \fi
    }%
  }%
  \skv@foreach@addtocallback{afterpre}{%
    \ifskv@foreach@swa
      % &lt;formula&gt; has the syntax \pgfmathparse{\x}.
      \skvexpandonce\skv@provc
      \let\skvexpandonce\skv@provb\noexpand\pgfmathresult
    \else
      % &lt;formula&gt; has the syntax \numexpr\x*2 or \dimexpr\x*2.
      % \ifskv@foreach@swb is true when a formula has been given.
      \edef\skvexpandonce\skv@provb{%
        \ifskv@foreach@swb\noexpand\the\fi
        \skvexpandonce\skv@provc\skv@tempd
      }%
    \fi
  }%
  \skvaftergroupdef\skv@foreach@afterprecallback\endgroup
}

% pgfmath parse=&lt;holder.macro&gt; as &lt;child.macro&gt; using &lt;formula&gt;
%
% 1. Evaluation is always done with \pgfmathparse.
%
% 2. &lt;formula&gt; must be \pgfmathparse-able.
%
\skvrobustdef*\skv@foreach@parsepgfmathparse#1{%
  \begingroup
  \ifdefined\pgfmathparse\else
    \skv@err{No \string\pgfmathparse; 'pgfmath' module not loaded}\skv@ehd
  \fi
  \def\skv@tempxifin##1##2{%
    \skvxifinTF{\detokenize{##1}}{\detokenize{##2}}%
  }%
  \skv@foreach@swafalse
  \def\skv@tempa##1as##2using##3\skv@nil{%
    \edef\skv@prova{\skvtrimspace{##1}}%
    \edef\skv@provb{\skvtrimspace{##2}}%
    \edef\skv@provc{\skvtrimspace{##3}}%
    \ifx\skv@prova\@empty
      \skv@err{Value of key 'pgfmath parse' has no holder macro}\skv@ehd
    \else
      \expandafter\skvifescapedTF\expandafter{\skv@prova}{%
        \expandafter\skvifntypeTF\expandafter{\skv@prova}{}{%
          \skv@err{Value of key 'pgfmath parse': more than 1
            \MessageBreak token \skvoxdetok\skv@prova.
            \MessageBreak I can't find holder macro}\skv@ehd
        }%
      }{%
        \skv@err{Value of key 'pgfmath parse':
          \MessageBreak holder macro \skvoxdetok\skv@prova not escaped}\skv@ehd
      }%
    \fi
    \ifx\skv@provb\@empty
      \skv@err{Value of key 'pgfmath parse' has no child macro}\skv@ehd
    \else
      \expandafter\skvifescapedTF\expandafter{\skv@provb}{%
        \expandafter\skvifntypeTF\expandafter{\skv@provb}{}{%
          \skv@err{Value of key 'pgfmath parse': more than 1
            \MessageBreak token \skvoxdetok\skv@provb.
            \MessageBreak I can't find child macro}\skv@ehd
        }%
      }{%
        \skv@err{Value of key 'pgfmath parse':
          \MessageBreak child \skvoxdetok\skv@provb not escaped}\skv@ehd
      }%
    \fi
    \ifx\skv@provc\@empty
      \skv@err{Value of key 'pgfmath parse' has no formula or
        \MessageBreak holder macro to be expanded}\skv@ehd
    \fi
    \skv@tempxifin{\pgfmathparse}{##3}{%
      \def\skv@tempc####1\pgfmathparse####2\skv@nil{%
        \ifx\@nnil####1\@nnil
          \skv@foreach@swatrue
        \else
          \skv@err{Invalid token \detokenize{####1}
            \MessageBreak before \string\pgfmathparse}\skv@ehd
        \fi
      }%
      \expandafter\skv@tempc\skv@provc\skv@nil
    }{%
      \skv@tempxifin{\numexpr}{##3}{%
        \skv@err{Value of key 'pgfmath parse':
          \MessageBreak\noexpand\numexpr not allowed}\skv@ehd
      }{%
        \skv@tempxifin{\dimexpr}{##3}{%
          \skv@err{Value of key 'pgfmath parse':
            \MessageBreak\noexpand\dimexpr not allowed}\skv@ehd
        }{%
          \skv@foreach@swatrue
          \edef\skv@provc{\noexpand\pgfmathparse{\skvexpandonce\skv@provc}}%
        }%
      }%
    }%
  }%
  \skv@tempxifin{using}{#1}{%
    \skv@tempxifin{as}{#1}{%
      % 'as' and 'using' are present: maybe there is a formula.
      \skv@tempa#1\skv@nil
    }{%
      \skv@err{Value of key 'pgfmath parse':
        \MessageBreak there is 'using', but no 'as'}\skv@ehd
    }%
  }{%
    \skv@tempxifin{as}{#1}{%
      \def\skv@tempb##1as##2##3\skv@nil{%
        \ifx\@nnil##1\@nnil
          \skv@err{Value of key 'pgfmath parse' has no holder macro}\skv@ehd
        \else
          \ifx\@nnil##2%
            \skv@err{Value of key 'pgfmath parse' has no child macro}\skv@ehd
          \else
            \skv@tempa##1as##2using##1\skv@nil
          \fi
        \fi
      }%
      \skv@tempb#1{\@nnil}\skv@nil
    }{%
      % No 'as' or 'using': #1 should be only the holder macro:
      \ifx\@nnil#1\@nnil
        \skv@err{Value of key 'pgfmath parse' has no holder macro}\skv@ehd
      \else
        \skvifntypeTF{#1}{%
          % Evaluate the holder macro:
          \skv@tempa#1as#1using#1\skv@nil
        }{%
          \skv@err{Value of key 'pgfmath parse': more than 1
            \MessageBreak token '\detokenize{#1}'.
            \MessageBreak I can't find holder macro}\skv@ehd
        }%
      \fi
    }%
  }%
  \skv@foreach@addtocallback{afterpre}{%
    \ifskv@foreach@swa
      \skvexpandonce\skv@provc
      \let\skvexpandonce\skv@provb\noexpand\pgfmathresult
    \fi
  }%
  \skvaftergroupdef\skv@foreach@afterprecallback\endgroup
}

% count in = \y all \x satisfying &lt;condition&gt; initially &lt;value&gt;
%
% 1. &lt;condition&gt; must be a balanced and valid TeX conditional, like
%
%    \ifnum\x&gt;2\fi, \ifx\x\@empty\fi
%
% 2. The aim is to allow general conditions (not only those involving
%    numerals) to be submitted.
%
% 3. PGF's \foreach doesn't have this feature; it has only a general
%    counter, eg,
%
%    '\foreach \x [count=\xi] in {a,...,e}'.
%
%    Generic counting is available in \newforeach 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:
%
%    \ifforeachlastitem \typeout{Processing last entry of the list} \fi
%
% 4. Counting is done from 1 (zero) unless &lt;value&gt; is given after
%    'initially'.
%
\skvrobustdef*\skv@foreach@parsecountin#1{%
  \begingroup
  \def\skv@tempxifin##1##2{%
    \skvxifinTF{\detokenize{##1}}{\detokenize{##2}}%
  }%
  \def\skv@tempa##1\skv@nil{%
    \skv@tempxifin{initially}{##1}{%
      \skv@tempb##1\skv@nil
    }{%
      \skv@tempb##1initially\skv@nil
    }%
  }%
  \def\skv@tempb##1all##2satisfying##3initially##4\skv@nil{%
    \edef\skv@prova{\skvtrimspace{##1}}%
    \edef\skv@provb{\skvtrimspace{##2}}%
    \edef\skv@provc{\skvtrimspace{##3}}%
    \edef\skv@provd{\skvtrimspace{##4}}%
    \ifx\skv@prova\@empty
      \skv@err{Value of key 'count' has no counter macro}\skv@ehd
    \else
      \expandafter\skvifescapedTF\expandafter{\skv@prova}{%
        \expandafter\skvifntypeTF\expandafter{\skv@prova}{}{%
          \skv@err{Value of key 'count in': more than 1
            \MessageBreak token \skvoxdetok\skv@prova.
            \MessageBreak I can't find counter macro}\skv@ehd
        }%
      }{%
        \skv@err{Value of key 'count':\MessageBreak
          counter macro \skvoxdetok\skv@prova not escaped}\skv@ehd
      }%
    \fi
    \ifx\skv@provd\@empty
      \expandafter\def\skv@prova{0}%
    \else
      \skvifintegerTF\skv@provd{%
        \expandafter\let\skv@prova\skv@provd
      }{%
        \skv@err{Value of key 'count':\MessageBreak
          initial \skvoxdetok\skv@provd not an integer}\skv@ehd
      }%
    \fi
    \skv@foreach@swafalse
    \ifx\skv@provc\@empty
      % No tester but there may be a holder macro to test. The holder
      % macro, on its own, isn't sufficient to conduct a test:
      \let\skv@foreach@itemcounter\skv@prova
    \else
      \ifx\skv@provb\@empty\else
        % If there isn't a holder macro or quantity to test, then no
        % test is possible:
        \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}\skv@ehd
          }%
        }{%
          \skv@err{Value of key 'count':\MessageBreak
            holder macro \skvoxdetok\skv@provb not escaped}\skv@ehd
        }%
        \skv@foreach@swatrue
        % \skv@tester is the second argument of \skv@foreach@maketester.
        % \skv@tester is used in pushing the item counter:
        \skvexpbracenext\skv@foreach@maketester\skv@provc\skv@tester\skvz@
      \fi
    \fi
  }%
  \skv@tempxifin{satisfying}{#1}{%
    \skv@tempxifin{all}{#1}{%
      % 'all' and 'satisfying' are present:
      \skv@tempa#1\skv@nil
    }{%
      \skv@err{Value of key 'count':
        \MessageBreak there is 'satisfying', but no 'all'}\skv@ehd
    }%
  }{%
    \skv@tempxifin{all}{#1}{%
      \skv@tempa#1satisfying\skv@nil
    }{%
      % No 'all' or 'satisfying': #1 should be only the counter macro:
      \ifx\@nnil#1\@nnil
        \skv@err{Value of key 'count' has no counter macro}\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}\skv@ehd
        }%
      \fi
    }%
  }%
  \ifskv@foreach@swa
    \skv@foreach@addtocallback{afterpre}{%
      \noexpand\ifnum\noexpand\foreachitemcount=\@ne
        \def\skvexpandonce\skv@prova{\number\skv@prova}%
      \noexpand\fi
      \skvexpandonce\skv@tester{%
        \noexpand\skvpushnumber\skvexpandonce\skv@prova
      }{}%
    }%
  \fi
  \skvexpanded{\endgroup
    \ifskv@foreach@swa
      \skvcmdexit\skv@foreach@afterprecallback
    \else
      \skvcmdexit\skv@foreach@itemcounter
    \fi
  }%
}

% remember=&lt;holder.macro&gt; as &lt;child.macro&gt; initially &lt;value&gt;
%
\skvrobustdef*\skv@foreach@parseremember#1{%
  \begingroup
  \def\skv@tempxifin##1##2{%
    \skvxifinTF{\detokenize{##1}}{\detokenize{##2}}%
  }%
  \skv@tempxifin{(}{#1}{%
    \skv@err{Value of key 'remember': '(' found.
      \MessageBreak I don't accept this PGF format.
      \MessageBreak Remove the parenthesis '(&lt;your input&gt;)'}\skv@ehd
  }{}%
  \def\skv@tempa##1as##2initially##3\skv@nil{%
    \edef\skv@prova{\skvtrimspace{##1}}%
    \edef\skv@provb{\skvtrimspace{##2}}%
    \edef\skv@provc{\skvtrimspace{##3}}%
    \skv@foreach@swafalse
    \ifx\skv@prova\@empty
      \skv@err{Value of key 'remember' has no holder macro:
        \MessageBreak i.e., no macro that holds input}\skv@ehd
    \else
      \expandafter\skvifescapedTF\expandafter{\skv@prova}{}{%
        \skv@err{Value of key 'remember':
          \MessageBreak Holder macro \skvoxdetok\skv@prova not escaped}\skv@ehd
      }%
    \fi
    \ifx\skv@provb\@empty
      \skv@err{Value of key 'remember' has no child macro;
        \MessageBreak i.e., no macro after 'as'}\skv@ehd
    \else
      \expandafter\skvifescapedTF\expandafter{\skv@provb}{%
        \skv@foreach@swatrue
      }{%
        \skv@err{Value of key 'remember':
          \MessageBreak Child \skvoxdetok\skv@provb not escaped}\skv@ehd
      }%
    \fi
  }%
  \skv@tempxifin{initially}{#1}{%
    \skv@tempxifin{as}{#1}{%
      \skv@tempa#1\skv@nil
    }{%
      \skv@err{Value of key 'remember':
        \MessageBreak There is 'initially', but no 'as'}\skv@ehd
    }%
  }{%
    \skv@tempxifin{as}{#1}{%
      \skv@tempa#1initially\skv@nil
    }{%
      % No 'as' and 'initially':
      \edef\skv@prova{\skvtrimspace{#1}}%
      \ifx\skv@prova\@empty\else
        % Go and raise error in \skv@tempa:
        \skv@tempa#1as initially\skv@nil
      \fi
    }%
  }%
  \ifskv@foreach@swa
    % Initially:
    \skv@foreach@addtocallback{pre}{%
      % Don't remove this \ifnum, otherwise the initial assignment
      % will be overwritten on subsequent returns:
      \noexpand\ifnum\noexpand\foreachitemcount=\@ne
        \edef\skvexpandonce\skv@provb{%
          \noexpand\unexpanded{\skvexpandonce\skv@provc}%
        }%
      \noexpand\fi
    }%
    \skv@foreach@addtocallback{post}{%
      \let\skvexpandonce\skv@provb\skvexpandonce\skv@prova
    }%
  \fi
  \skvexpanded{\endgroup
    \ifskv@foreach@swa
      \skvcmdexit\skv@foreach@precallback
      \skvcmdexit\skv@foreach@postcallback
    \fi
  }%
}

% recall=&lt;holder.macro&gt; initially &lt;value&gt;.
%
% This builds a retainer macro of the form \&lt;foreachlast&gt;&lt;holder.name&gt;.
%
% 'as' is invalid/illegal here, since a retainer macro is built internally.
%
\skvrobustdef*\skv@foreach@parserecall#1{%
  \begingroup
  \def\skv@tempxifin##1##2{%
    \skvxifinTF{\detokenize{##1}}{\detokenize{##2}}%
  }%
  \skv@tempxifin{(}{#1}{%
    \skv@err{Value of key 'recall': '(' found.
      \MessageBreak I don't accept this PGF format.
      \MessageBreak remove the parenthesis '()'}\skv@ehd
  }{}%
  \skv@foreach@swafalse
  \def\skv@tempa##1initially##2\skv@nil{%
    \edef\skv@prova{\skvtrimspace{##1}}%
    \edef\skv@provb{\skvtrimspace{##2}}%
    \ifx\skv@prova\@empty
      \skv@err{Value of key 'recall' has no holder macro:
        \MessageBreak i.e., no macro that holds input}\skv@ehd
    \else
      \expandafter\skvifntypeTF\expandafter{\skv@prova}{%
        \expandafter\skvifescapedTF\expandafter{\skv@prova}{%
          \edef\skv@elt{\expandafter\skvremovescape\skv@prova}%
          \skv@foreach@swatrue
          % Initially:
          \skv@foreach@addtocallback{pre}{%
            % Don't remove this \ifnum, otherwise the initial assignment
            % will be overwritten on subsequent returns:
            \noexpand\ifnum\noexpand\foreachitemcount=\@ne
              \skvcsedef{foreachlast\skv@elt}{%
                \noexpand\unexpanded{\skvexpandonce\skv@provb}%
              }%
            \noexpand\fi
          }%
          \skv@foreach@addtocallback{post}{%
            \skvcslet{foreachlast\skv@elt}\skvexpandonce\skv@prova
          }%
        }{%
          \skv@err{Value of key 'recall':
            \MessageBreak \detokenize{#1} is not escaped}\skv@ehd
        }%
      }{%
        \skv@err{Value of key 'recall':
          \MessageBreak \detokenize{#1} is not one token}\skv@ehd
      }%
    \fi
  }%
  \skv@tempxifin{as}{#1}{%
    \skv@err{Value of key 'recall': invalid 'as' found.
      \MessageBreak This key doesn't expect 'as' since
      \MessageBreak it automatically builds a retainer macro
      \MessageBreak of the form \&lt;foreachlast&gt;&lt;holder.name&gt;}\skv@ehd
  }{%
    \skv@tempxifin{initially}{#1}{%
      \skv@tempa#1\skv@nil
    }{%
      \ifx\@nnil#1\@nnil\else
        \skv@tempa#1initially\skv@nil
      \fi
    }%
  }%
  \skvexpanded{\endgroup
    \ifskv@foreach@swa
      \skvcmdexit\skv@foreach@precallback
      \skvcmdexit\skv@foreach@postcallback
    \fi
  }%
}
% \skv@foreach@doreverselist{&lt;parser&gt;}{&lt;listcmd&gt;}
\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&lt;value&gt;\skv@nil...\skv@nnil\skv@stop
\skvnewdef*\skv@dots@in#1...#2#3\skv@stop{%
	\ifx\skv@nnil#2\in@false\else\in@true\fi
}

\skvrobustdef*\skv@foreach@latehookerr{%
  \def\skv@foreach@latehook{%
    \begingroup
    \let\s\string
    \skv@err{A \noexpand\newforeach hook (\s\prependtobeginforeach,
      \MessageBreak\s\appendtobeginforeach, \s\atbeginforeach,
      \MessageBreak\s\prependtoendforeach, \s\appendtoendforeach,
      \MessageBreak or \s\atendforeach) has been illegally
      \MessageBreak issued within \s\newforeach}
      {\s\newforeach\space hook command shouldn't be issued
        within \s\newforeach.}%
    \endgroup
  }%
  \skvletmanytocmd{%
    \prependtobeginforeach,\appendtobeginforeach,\atbeginforeach,
    \prependtoendforeach,\appendtoendforeach,\atendforeach
  }\skv@foreach@latehook
}

\skvrobustdef*\skv@foreach@pushstate{%
  \skvsavestate\skv@foreach@stack{%
    \do\skv@foreach@starform\do\skv@foreach@parser
    \do\skv@foreach@subparser\do\skv@foreach@listisamacro
    \do\skv@foreach@processupto\do\skv@foreach@processempty
    \do\skv@foreach@exittester\do\skv@foreach@continuetester
    \do\skv@foreach@grow\do\skv@foreach@growleft\do\skv@foreach@growright
    \do\skv@foreach@terminator\do\skv@foreach@recoverholders
    \do\skv@foreach@normalizelist\do\skv@foreach@callback
    \do\skv@foreach@hideparameters\do\skv@foreach@callback@hiddenparameters
    \do\skv@foreach@auxcallback\do\skv@foreach@precallback
    \do\skv@foreach@afterprecallback\do\skv@foreach@postcallback
    \do\skv@foreach@onlyinitially
    \do\foreachlistremainder\do\skv@foreach@mainloop
    \do\skv@foreach@getnext\do\skv@foreach@picknext\do\skv@foreach@getrm
    \do\skv@foreach@do@a\do\skv@foreach@do@b
    % Macros '...lookahead...' need stacking in \foreachfox and when
    % \newforeach is nested with \foreachfox:
    \do\skv@foreach@lookahead@a\do\skv@foreach@lookahead@b
    \do\skv@foreach@lookahead@c\do\skv@foreach@lookahead@d
    \do\skv@foreach@paramlist\do\skv@foreach@holderlist
    \do\skv@foreach@userlist\do\skv@foreach@inherit
    \do\skv@foreach@keepdecimals\do\skv@foreach@keephighdecimals
    \do\skv@foreach@itemcounter\do\skv@foreach@link
    \do\skv@foreach@expandbeforefill\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 here:
    \do\prependtobeginforeach\do\appendtobeginforeach\do\atbeginforeach
    \do\prependtoendforeach\do\appendtoendforeach\do\atendforeach
  }\foreachnestdepth
}
\skvrobustdef*\skv@foreach@popstate{%
  \skvrestorestate\skv@foreach@stack\foreachnestdepth
}
\skvnewlet\skv@foreach@nil\relax
\skvnewdef*\skv@foreach@nnil{\skv@foreach@nil}
\skvrobustdef*\newforeach{\skv@testst\skv@newforeach@beginprescan}
\skvrobustdef*\skv@newforeach@beginprescan{%
  \skv@inforeachtrue
  \edef\skv@foreach@starform{0\ifskv@tempst0\else1\fi}%
  \begingroup
  \def\skv@foreach@holderlist{}%
  \def\skv@tempa{%
    \skvexpanded{\endgroup
      \noexpand\skv@foreach@endprescan
        {\skvexpandonce\skv@foreach@holderlist}%
    }%
  }%
  \let\bgroup\relax
  \skvifnextchar[{%
    \endgroup\skv@foreach@scanarg
  }{%
    \skvifnextchar i{%
      \endgroup
      \skv@err{\string\newforeach: no holder macro seen}\skv@ehd
    }{%
      \skvifnextchar\skv@orig@bgroup{%
        \endgroup
        \skv@err{\string\newforeach: no holder macro seen}\skv@ehd
      }{%
        \skv@foreach@collectholders
      }%
    }%
  }%
}
\skvrobustdef*\skv@foreach@collectholders#1{%
  \edef\skv@foreach@holderlist{%
    \skvexpandonce\skv@foreach@holderlist\skvtrimspace{#1}%
  }%
  \skvifnextchar[{%
    \skv@tempa
  }{%
    \skvifnextchar i{%
      \skv@tempa[]%
    }{%
      \skvifnextchar\skv@orig@bgroup{%
        \skv@tempa[]%
      }{%
        \skv@foreach@collectholders
      }%
    }%
  }%
}
\skvrobustdef*\skv@foreach@endprescan#1[#2]{%
  \skvifblankTF{#1}{%
    \skv@err{\string\newforeach: no holder macros seen}\skv@ehd
  }{%
    \skv@foreach@scanarg[#2]#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:
  \def\foreachitemcount{0}%
  % Don't confuse macros of various depths; reset them here:
  \def\do##1{\def##1{}}%
  \do\skv@foreach@itemcounter\do\skv@foreach@processupto
  \do\skv@foreach@callback\do\skv@foreach@auxcallback
  \do\skv@foreach@callback@hiddenparameters
  \do\skv@foreach@precallback\do\skv@foreach@afterprecallback
  \do\skv@foreach@postcallback\do\skv@foreach@onlyinitially
  % The keys have to be set here, to determine if the list is a macro, etc.
  % Since \skv@foreach@precallback are initialized in each nest, the
  % keys have to be reset here. Reset all keys: they might have been
  % fixed by the outer loop and the inner loop might assume the default
  % values of the keys are those being used.
  \skv@foreach@setkeys{#1}%
  % We've set the keys; let's overrule \skv@foreach@expandlistonce if
  % we had seen a star suffix. Don't overrule \skv@foreach@expandlisttwice
  % and \skv@foreach@expandlistfully.
  \if\skv@foreach@starform
    \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
    \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@foreach@holderlist{}%
  \let\bgroup\relax
  \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@scanarg@b#1{%
  % Odd items must be subparser:
  \ifodd\skv@cnta
    \ifnum\skv@cnta=\@ne
      \skvifescapedTF{#1}{%
        \skv@err{Token '\noexpand#1' cannot be a subparser;
          \MessageBreak it seems to be a holder macro. I expected
          \MessageBreak the subparser to be the token here.}\skv@ehd
      }{%
        \edef\skv@prova{\skvtrimspace{#1}}%
        \let\elt\skvexpandonce
        \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 '\elt\skv@elt'.
              \MessageBreak I have used '\elt\skv@prova', but please submit
              \MessageBreak '\elt\skv@prova' as the value of the key
              'subparser'
              \MessageBreak so that I can stop giving this warning.
            }%
          \fi
          \let\skv@foreach@subparser\skv@prova
        \fi
      }%
    \fi
  \else
    \skvifescapedTF{#1}{}{%
      \skv@err{Token '\noexpand#1' is not escaped
        \MessageBreak and can't be a holder macro}\skv@ehd
    }%
  \fi
  \advance\skv@cnta\@ne
  \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@scanarg@c#1#2{%
  \skvifstrcmpTF{#1#2}{in}{%
    \skv@foreach@scanarg@d
  }{%
    \skv@err{I have seen 'i' but no expected 'in'}\skv@ehd
  }%
}
\skvrobustdef*\skv@foreach@scanarg@d{%
  \ifx\skv@foreach@holderlist\@empty
    \skv@err{No item holder macros before 'in'
      \MessageBreak or before left brace}\skv@ehd
  \fi
  \skvifnextchar\skv@orig@bgroup{%
    \skv@foreach@scanarg@e
  }{%
    \if\skv@foreach@listisamacro
      \expandafter\skv@foreach@scanarg@e
    \else
      \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\skv@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 'expand list once'
          \MessageBreak or 'expand list twice' or 'list is a macro', etc.%
        }\skv@tempehd
      }%
      \expandafter\reserved@a
    \fi
  }%
}
% #1: &lt;list&gt; or &lt;listcmd&gt;
\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@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'}\skv@ehd
  }%
}
% We've exhausted all options for grabbing the callback, so now
% 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=&lt;parser&gt;'.
      % 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.
      \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
            \noexpand\newforeach and needs to be enclosed in braces.
            The '##1' I have just encountered doesn't seem to be the
            one ending a TikZ object. Maybe you need to do [parser={##1}].}%
        }{%
          % Otherwise, let's try continue:
          \skvexpanded{%
            \noexpand\skv@foreach@scanarg@h{\skvtrimspace{####1}##1}%
          }%
        }%
      }{%
        \skvexpanded{%
          \noexpand\skv@foreach@scanarg@h{\skvtrimspace{####1}##1}%
        }%
      }%
    }%
    \skv@prova
  }%
  % In case callback terminator is currently active, rescan it.
  \skvrescan\skv@foreach@terminator
  \expandafter\skv@prova\expandafter{\skv@foreach@terminator}%
}
% #1: callback
\skvrobustdef*\skv@foreach@scanarg@h#1{%
  \skvexpanded{\endgroup
    % The subparser may have changed along the way
    % (see \skv@foreach@scanarg@b):
    \skvcmdexit\skv@foreach@subparser
    \skv@foreach@mainprocess
      {\skvexpandonce\skv@foreach@holderlist}%
      {\skvexpandonce\skv@foreach@userlist}%
      {\skvtrimspace{#1}}%
  }%
}
% #1: holder macros
% #2: List or list command
% #3: Callback
\skvrobustdef*\skv@foreach@mainprocess#1#2#3{%
  \edef\skv@foreach@userlist{%
    \if\skv@foreach@expandlistonce
      \expandafter\skvexpandonce
    \else
      \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\foreachnestdepth}%
  \skvifdefTF\foreachprevitem{}{\def\foreachprevitem{}}%
  \expandafter\skv@foreach@normalize\expandafter[\skv@foreach@parser]%
    \skv@foreach@userlist
  % Why 'keep double parser' here? Think of a list like 32//13,11/23/,...
  \skvexpbracenext\skvdefinekeepdoubleparsernormalizer
    \skv@foreach@subparser\skv@tempa
  \edef\skv@foreach@userlist{\skvexpbracenext\skv@tempa\skv@foreach@userlist}%
  \ifnum\foreachnestdepth=\skvz@
    \breakallforeachloopsfalse
  \fi
  \skvbreakloopfalse
  \foreachlastitemfalse
  \def\skv@foreach@lookahead@a##1{%
    \def\skv@foreach@picknext{##1.}%
    \futurelet\skv@foreach@next\skv@foreach@lookahead@b
  }%
  \def\skv@foreach@lookahead@b{%
    \ifx\skv@foreach@next[%
      \expandafter\skv@foreach@lookahead@c
    \else
      \ifx\skv@foreach@next(%
        \expandafter\expandafter\expandafter\skv@foreach@lookahead@d
      \else
        \expandafter\expandafter\expandafter\skv@foreach@picknext
      \fi
    \fi
  }%
  \def\skv@foreach@lookahead@c[##1]{\skv@foreach@picknext[{##1}]}%
  \def\skv@foreach@lookahead@d(##1){\skv@foreach@picknext({##1})}%
  \def\skv@foreach@mainloop##1{%
    \def\skv@foreach@getnext####1##1####2\skv@foreach@stop{%
      \edef\foreachnextitem{\skvexpandonce{\@gobble####1}}%
      \ifx\foreachnextitem\skv@foreach@nnil
        \foreachlastitemtrue
        \def\foreachnextitem{}%
      \fi
    }%
    \def\skv@foreach@do@a####1##1####2\skv@foreach@stop{%
      \edef\foreachcurrentitem{\skvexpandonce{\@gobble####1}}%
      \skvifxTF\foreachcurrentitem\skv@foreach@nnil{%
        \skvbreakloopfalse
        \foreachlastitemfalse
      }{%
        \skvifxTF\foreachcurrentitem\skv@listbreakertoks{%
          \skv@foreach@getrm{####2}%
        }{%
          \skvifxTF\foreachcurrentitem\skv@listpausertoks{%
            \message{^^J! List pause:
              ^^JType x or X to quit, or &lt;RETURN&gt; to proceed^^J}%
            \begingroup
            \endlinechar\m@ne\global\read-1 to\@gtempa
            \endgroup
            \skvexpandarg\lowercase{\def\noexpand\@gtempa{\@gtempa}}%
            \skvxifstrcmpTF\@gtempa{x}{%
              \skv@foreach@getrm{####2}%
            }{%
              \skv@foreach@do@b{####2}%
            }%
          }{%
            \skv@foreach@do@b{####2}%
          }%
        }%
      }%
    }%
    \def\skv@foreach@do@b####1{%
      \edef\foreachitemcount{\the\numexpr\foreachitemcount+1}%
      \ifx\skv@foreach@itemcounter\@empty\else
        \expandafter\let\skv@foreach@itemcounter\foreachitemcount
      \fi
      \skv@foreach@lookahead@a\skv@foreach@getnext####1\skv@foreach@stop
      % If the user decides to continue after \foreachlistpauser is picked up,
      % don't use \foreachlistpauser as an item:
      \skvifxTF\foreachcurrentitem\skv@listpausertoks{}{%
        \skvexpbracenext\skv@foreach@callback\foreachcurrentitem
        \let\foreachprevitem\foreachcurrentitem
      }%
      \ifx\skv@foreach@processupto\@empty\else
        \ifnum\foreachitemcount&lt;\skv@foreach@processupto\relax\else
          \skvbreakloop
        \fi
      \fi
      \skvifdefboolTF{skvbreakloop}{%
        \skv@foreach@getrm{####1}%
      }{%
        \skv@foreach@lookahead@a\skv@foreach@do@a####1\skv@foreach@stop
      }%
    }%
    \def\skv@foreach@getrm####1{%
      \ifbreakallforeachloops\else
        \skvbreakloopfalse
      \fi
      \foreachlastitemfalse
      \def\skv@prova########1\skv@foreach@nil##1{%
        \edef\foreachlistremainder{\unexpanded{########1}}%
        \skv@removetrailingparser{##1}\foreachlistremainder
      }%
      \skv@prova####1%
    }%
    \skvifxTF\skv@foreach@userlist\@empty{%
      \if\skv@foreach@processempty\skvafterfi
        \skv@foreach@callback{}%
      \fi
    }{%
      \def\do####1{\if####1true\else false\fi}%
      \skvexpandsecond{\skvautocompletelist*}{[%
        % Note: the value of 'expand list once', etc., can't be
        % transferred automatically to \skvautocompletelist since they
        % have been used above to expand list.
        parser={\skv@foreach@parser},
        link={\skvexpandonce\skv@foreach@link},
        grow left=\do\skv@foreach@growleft,
        grow right=\do\skv@foreach@growright,
        keep decimals=\do\skv@foreach@keepdecimals,
        keep high decimals=\do\skv@foreach@keephighdecimals,
        expand before fill=\do\skv@foreach@expandbeforefill
      ]}\skv@foreach@userlist\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
    }%
  }%
  \skv@foreach@makeprecode{#1}%
  \if\skv@foreach@recoverholders\else
    \expandafter\skvsavestate\expandafter\skv@foreach@holderstate
      \expandafter{\skv@foreach@holderlist}\skv@foreach@holderdepth
  \fi
  \skv@foreach@makeauxcallback{#3}%
  \skvexpandbracenext\skv@foreach@mainloop\skv@foreach@parser
  \skvcsuse{skv@foreach@atendhook@\skvrom\foreachnestdepth}%
  \if\skv@foreach@recoverholders\else
    \skvrestorestate\skv@foreach@holderstate\skv@foreach@holderdepth
  \fi
  \skv@foreach@popstate
  \ifnum\foreachnestdepth=\skvz@
    \def\skv@warnsubparser{0}%
  \fi
  \skv@inforeachfalse
}

% \skv@foreach@makeprecode{&lt;holder.list&gt;}
%
% 'Holder macro' here means, eg, \x and \y in
%
%    \newforeach \x/\y in {1/a,2/b,3/c}{&lt;code&gt;}
%
\skvrobustdef*\skv@foreach@makeprecode#1{%
  \begingroup
  \skv@cnta\skvz@
  \def\skv@foreach@holderlist{}%
  \def\skv@foreach@paramlist{}%
  \def\skv@prevholder{}%
  \def\skv@tempa{#1}%
  \expandafter\skv@foreach@normalize\expandafter
    [\skv@foreach@subparser]\skv@tempa
  \skvtfor*\skv@prova:=\skv@tempa\do{%
    \ifx\skv@prova\skv@foreach@subparser
      \ifnum\skv@cnta=\skvz@
        \skv@err{Subparser '\skvoxdetok\skv@foreach@subparser' can't come
          first in the list\MessageBreak of holder macros}\skv@ehd
      \else
        % Eg, if subparser is slash (/), \skv@foreach@paramlist will have
        % the syntax: ##1/##2/...:
        \edef\skv@foreach@paramlist{%
          \skvexpandonce\skv@foreach@paramlist\skvexpandonce\skv@prova
        }%
      \fi
    \else
      \advance\skv@cnta\@ne
      \edef\skv@elt{\expandafter\skvremovescape\skv@prova}%
      \edef\skv@foreach@precallback{%
        \skvexpandonce\skv@foreach@precallback
        % Each given item-holder macro is now defined in terms of
        % parameters of skv@foreach@auxcallback:
        \edef\skvexpandonce\skv@prova{%
          \noexpand\unexpanded{####\number\skv@cnta}%
        }%
        % If the current holder has no value, use the value of last holder:
        \ifnum\skv@cnta&gt;\@ne
          \if\skv@foreach@inherit
            \noexpand\ifx\skvexpandonce\skv@prova\noexpand\@empty
              \let\skvexpandonce\skv@prova\skvexpandonce\skv@prevholder
            \noexpand\fi
          \fi
        \fi
      }%
      \edef\skv@foreach@holderlist{%
        \skvexpandonce\skv@foreach@holderlist
        % The \do is for the individual entries of the stack of
        % \skv@foreach@holderlist. It is required for stacking the
        % holder list:
        \noexpand\do\skvexpandonce\skv@prova
      }%
      \edef\skv@foreach@paramlist{%
        \skvexpandonce\skv@foreach@paramlist########\number\skv@cnta
      }%
      \let\skv@prevholder\skv@prova
    \fi
  }%
  % Add one extra parameter character to absorb extra subparsers that are
  % added for incomplete list items:
  \edef\skv@foreach@paramlist{%
    \skvexpandonce\skv@foreach@paramlist
    \skvexpandonce\skv@foreach@subparser
    ########\number\numexpr\skv@cnta+1\relax
  }%
  \skvexpanded{\endgroup
    \skvcmdexit\skv@foreach@holderlist
    \skvcmdexit\skv@foreach@paramlist
    \skvcmdexit\skv@foreach@precallback
  }%
}
% Example (*):
%
% This example demonstrates why \skv@foreach@continuetester must be
% located delicately, at where it is currently.
%
% \def\ditem{D}
% \newforeach [
%   continue=\ifx\x\ditem\fi, remember=\x as \rx initially A
% ] \x in {
%   B,(C1),D,E,[F1],G,H
% }{%
%   $\overrightarrow{\rx\x}$\ifforeachlastitem.\else,\space\fi
% }
%
% #1: callback
\skvrobustdef*\skv@foreach@makeauxcallback#1{%
  \begingroup
  \def\skv@generatesubparser##1{%
    \ifnum##1&lt;10 \skvexpandonce\skv@foreach@subparser
      \expandafter\skv@generatesubparser
      \expandafter{\number\numexpr##1+1\expandafter}%
    \fi
  }%
  % Add extra subparsers in case some items aren't subparser-complete:
  \edef\skv@tempa{\skv@generatesubparser{1}}%
  \edef\skv@foreach@callback@hiddenparameters{\unexpanded{#1}}%
  \let\foreacheov\relax
  \let\do\noexpand
  \skvexpanded{\endgroup
    \skvcmdexit\skv@foreach@callback@hiddenparameters
    % Define auxiliary callback:
    \def\do\skv@foreach@auxcallback\skv@foreach@paramlist\foreacheov{%
      % Holder macro assignments:
      \skvexpandonce\skv@foreach@precallback
      % User tests/tasks, eg, if requested from 'evaluate' key:
      \skvexpandonce\skv@foreach@afterprecallback
      \do\ifnum\do\foreachitemcount=\@ne
        \do\skv@foreach@onlyinitially
      \do\fi
      \ifx\skv@foreach@continuetester\@secondoftwo
        \noexpand\skv@foreach@continuetester
      \else
        % Expose the parameter characters in \skv@foreach@continuetester.
        % If the user wants to ignore the callback for some items, he can
        % use the key 'continue=&lt;condition&gt;':
        \skvexpandonce\skv@foreach@continuetester
      \fi
      {%
        \relax
      }{%
        \if\skv@foreach@hideparameters
          \expandafter\@firstoftwo
        \else
          \expandafter\@secondoftwo
        \fi
        {%
          \noexpand\skv@foreach@callback@hiddenparameters
        }{%
          \unexpanded{#1}%
        }%
        % User tests/tasks, eg, if requested from the keys 'remember',
        % 'exit when', etc:
        \skvexpandonce\skv@foreach@postcallback
      }%
    }%
    % Define the real callback:
    \def\do\skv@foreach@callback####1{%
      \do\skv@foreach@auxcallback####1\skvxonce\skv@tempa\foreacheov
    }%
  }%
}
\skvnewdef*\skv@ucalpha#1{%
	\ifcase#1\or A\or B\or C\or D\or E\or F\or G\or H\or I\or J\or
  K\or L\or M\or N\or O\or P\or Q\or R\or S\or T\or U\or V\or W\or
  X\or Y\or Z\else?\fi
}
\skvnewdef*\skv@lcalpha#1{%
	\ifcase#1\or a\or b\or c\or d\or e\or f\or g\or h\or i\or j\or
  k\or l\or m\or n\or o\or p\or q\or r\or s\or t\or u\or v\or w\or
  x\or y\or z\else?\fi
}
\skvnewdef*\skv@alphamap{%
  {A}{a}{1}{B}{b}{2}{C}{c}{3}{D}{d}{4}{E}{e}{5}{F}{f}{6}{G}{g}{7}{H}{h}{8}%
  {I}{i}{9}{J}{j}{10}{K}{k}{11}{L}{l}{12}{M}{m}{13}{N}{n}{14}{O}{o}{15}%
  {P}{p}{16}{Q}{q}{17}{R}{r}{18}{S}{s}{19}{T}{t}{20}{U}{u}{21}{V}{v}{22}%
  {W}{w}{23}{X}{x}{24}{Y}{y}{25}{Z}{z}{26}%
}
\skvrobustdef*\skv@reverselumap#1{%
  \def\skv@prova##1##2##3##4\skv@nil{%
    \ifx\@nnil##1%
      \expandafter\@gobble
    \else
      \expandafter\@iden
    \fi
    {\skv@prova##4\skv@nil{##1}{##2}{##3}}%
  }%
  \edef#1{\expandafter\skv@prova\skv@alphamap\@nnil{}{}\skv@nil}
}


\skvquickkeys.define{skeyval/autocomplete}{%
  .exec/\def\skv@autocomplete@parser{,};
  parser/{,}/
    \edef\skv@autocomplete@parser{\unexpanded{#1}}
    \skvstripouterbraces{2}\skv@autocomplete@parser
    \skvxifntypeTF{\detokenize{#1}}{%
      \begingroup
      % It is assumed that every n-type parser and subparser
      % must have catcode 12:
      \skvexpandnext{\catcode`}\skv@autocomplete@parser=12\relax
      \skvrescan\skv@autocomplete@parser
      \skvaftergroupdef\skv@autocomplete@parser\endgroup
    }{}
  ;
  % This default value of 'link' is required by \skvautocompletelist:
  .exec code/\def\skv@autocomplete@link{\@nil};
  link/\@nil/
    \edef\skv@prova{\unexpanded{#1}}%
    \ifcase0%
      \ifx\skv@prova\@empty 1\fi
      \ifx\skv@prova\@nnil 1\fi\relax
      \edef\skv@autocomplete@link{\unexpanded{#1}}%
      \skvstripouterbraces{2}\skv@autocomplete@link
    \fi
  ;
  grow/\@nil/
    \edef\skv@prova{\unexpanded{#1}}%
    \ifx\skv@prova\@nnil\else
      \skvcsedef{skv@autocomplete@grow#1}{00}
      \edef\skv@prova{\skvifstrcmpTF{#1}{left}{right}{left}}%
      \skvcsedef{skv@autocomplete@grow\skv@prova}{01}%
    \fi
    /left,right
  ;
  .exec/
    \def\skv@autocomplete@growleft{01}
    \def\skv@autocomplete@growright{01}
  ;
  grow left/true/
    \edef\skv@autocomplete@growleft{0\skvifstrcmpTF{true}{#1}01}
    /true,false
  ;
  grow right/true/
    \edef\skv@autocomplete@growright{0\skvifstrcmpTF{true}{#1}01}
    /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@autocomplete@keepdecimals{0\skvifstrcmpTF{true}{#1}01}
    /true,false
  ;
  keep high decimals,keep only high decimals/true/
    \edef\skv@autocomplete@keephighdecimals{0\skvifstrcmpTF{true}{#1}01}
    /true,false
  ;
  expand before fill,expand list before fill/true/
    \edef\skv@autocomplete@expandbeforefill{0\skvifstrcmpTF{true}{#1}01}
    /true,false
  ;
}

% The keys 'link,grow' don't need presetting. The user must supply
% values when they are called. In internal loops, their values will
% have to be revised from those of the outer loop.
%
\skvquickkeys.preset{skeyval/autocomplete}{%
  parser,grow left=false,grow right=false,
  keep decimals=true,keep high decimals=false,
  expand before fill=false
}

% \skv@autocomplete@addtolist&lt;parser&gt;&lt;add.new&gt;&lt;listcmd&gt;
\skvrobustdef*\skv@autocomplete@addtolist#1#2#3{%
  \edef#3{\skvexpandonce#3\ifx#3\@empty\else\unexpanded{#1}\fi#2}%
}
% \skv@autocomplete@zerostepwarn{&lt;lower&gt;}{&lt;upper&gt;}{&lt;pt.or.nil&gt;}
\skvrobustdef*\skv@autocomplete@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' \ifskv@latex before \skv@begindoctoks\fi}%
}
% \skvautocompletelist[&lt;kvlist&gt;]{&lt;list&gt;}{&lt;returncmd&gt;}
% \skvautocompletelist*[&lt;kvlist&gt;]{&lt;listcmd&gt;}{&lt;returncmd&gt;}
%
% 1. Parse list of type {1,2,...,n,1,...,m} for auto completion.
%    Return outcome in &lt;listcmd&gt; or \skvcompletedlist.
%
\skvrobustdef*\skvautocompletelist{\skv@teststopt\skv@autocompletelist@a{}}
\skvrobustdef*\skv@autocompletelist@a[#1]#2#3{%
  \skv@usetempst{#2}\skv@autocomplete@userlist
  \skvquickkeys.set{skeyval/autocomplete}{#1}%
  \def\skv@inalphabetic{01}%
  \def\skv@isupperalpha{01}%
  \def\skv@preandpostdotspresent{01}%
  % If the list is alphabetic or numbers, original unit is nil:
  \def\skv@autocomplete@origunit{}%
  \def\skvcompletedlist{}%
  \skvexpandtwoargsonce
    \skv@autocompletelist@b\skv@autocomplete@parser\skv@autocomplete@userlist
  \let#3\skvcompletedlist
}
% \skv@autocompletelist@b{&lt;parser&gt;}{&lt;list&gt;}
\skvrobustdef*\skv@autocompletelist@b#1#2{%
  \edef\skv@tempa{\unexpanded{#2}}%
  \skv@foreach@normalize[#1]\skv@tempa
  \def\skv@prova##1{%
    \skvxifinTF{...}{\detokenize{##1}}{%
      \if\skv@autocomplete@expandbeforefill
        \edef\skv@tempa{##1}%
        \skv@foreach@normalize[#1]\skv@tempa
      \else
        \edef\skv@tempa{\unexpanded{##1}}%
      \fi
      \skvexpandargonce{\skv@autocompletelist@c{#1}}\skv@tempa
      \skv@foreach@normalize[#1]\skvcompletedlist
    }{%
      \edef\skvcompletedlist{%
        \skvaddlist{#1}\skvcompletedlist\skvtrimspace{##1}%
      }%
    }%
  }%
  \expandafter\skv@prova\expandafter{\skv@tempa}%
}
% \skv@autocompletelist@c{&lt;parser&gt;}{&lt;list&gt;}
\skvrobustdef*\skv@autocompletelist@c#1#2{%
  \skvxiffound{\relax...}\in{\relax\detokenize{#2}}\then
    \skv@err{I can't find lower limit before '...'}\skv@ehd
  \else
    \skvxiffound{\relax\detokenize{#1}...}\in{\relax\detokenize{#2}}\then
      \skv@err{I can't find lower limit before '...'}\skv@ehd
    \fi
  \fi
  % \newforeach format is '&lt;parser&gt;...&lt;parser&gt;':
  \skvxifinTF{\detokenize{#1...#1}}{\detokenize{#2}}{%
    \skv@autocomplete@splitbeforedots{#1}{#2}%
    \def\skv@prova##1#1##2#1...#1##3#1##4#1##5\skv@nil{%
      \skvifblankTF{##3}{%
        \skv@err{I can't find upper limit number or dimension,
          \MessageBreak i.e., after symbool '...'}\skv@ehd
      }{%
        % \skv@autocompletelist@b may be reentered. Hence accumulate
        % filled list:
        \skviflacus{##1}\then\else
          \edef\skvcompletedlist{%
            \skvaddlist{#1}\skvcompletedlist\unexpanded{##1}%
          }%
        \fi
        % Complete the list:
        \skv@autocompletelist@d{#1}{##1}{##2}{##3}%
        % In case the list is folded on ellipsis (...):
        \skvifblankTF{##4}{}{\skv@autocompletelist@b{#1}{##4#1##5}}%
      }%
    }%
    \expandafter\skv@prova\skv@tempa#1#1\skv@nil
  }{%
    \skv@autocompletelist@e{#1}{#2}%
  }%
}
% skv@autocompletelist@d{&lt;parser&gt;}{&lt;lower1&gt;}{&lt;lower2&gt;}{&lt;upperbound&gt;}
%
% 1. No &lt;guide&gt; here.
%
\skvrobustdef*\skv@autocompletelist@d#1#2#3#4{%
  \skvifxTF\skv@autocomplete@link\@nnil{%
    % No &lt;link&gt; has been given. The list has '...' but presumably no link.
    %
    % \skv@autocompletelist@h{&lt;parser&gt;}{&lt;guide&gt;}{&lt;lower1&gt;}{&lt;lower2&gt;}{&lt;upper&gt;}
    \skv@autocompletelist@h{#1}{}{#2}{#3}{#4}%
  }{%
    % &lt;link&gt; has been given by the user:
    \skv@autocomplete@splitandgrow{#1}{#2}{#3}{#4}%
  }%
}
%
% \skv@autocompletelist@e{&lt;parser&gt;}{&lt;list&gt;}
%
% \skv@autocompletelist@e will auto-complete this list without
% knowledge of the values of the keys 'link' and 'grow'. The syntax at (*)
% above isn't recognized by the auto-completion scheme of skeyval.
%
% skeyval formats:
%
%    {1pt,4pt,...pt,10pt}        : no additional info. required
%    {A_2pt,A_4pt,A_...,A_10pt}  : no additional info. required
%    {\pi0,\pi0.5,\pi...,\pi3}   : no additional info. required
%    {0\pi,0.5\pi,...\pi,3\pi}   : no additional info. required
%    {1pt,4pt,...,10pt}          : link = pt, grow=left, or no addit. info.
%    {A_2pt,A_4pt,...,A_10pt}    : link =_,   grow=right
%
% The general PGF format with left and right guides (given as 'A_'
% and 'pt') in
%
%    {A_2pt,A_4pt,A_...pt,A_10pt}
%
% is still legal in skeyval.
%
\skvrobustdef*\skv@autocompletelist@e#1#2{%
  \skv@autocomplete@splitbeforedots{#1}{#2}%
  \def\skv@checkguideinbounds##1##2{%
    \skv@foreach@swafalse
    \def\do####1{%
      \ifx\do####1\else
        \skviflacus####1\then\else
          \skvifinTF{##1}{####1}{}\skv@foreach@swatrue
        \fi
        \expandafter\do
      \fi
    }%
    \do##2\do
    \ifskv@foreach@swa
      \skv@err{Guide token '\detokenize{#1}' not found in some
        \MessageBreak of the elements: I can't complete
        \MessageBreak the current list. This may be
        \MessageBreak due to wrong direction of growth}\skv@ehd
    \fi
  }%
  \def\skv@prova##1#1##2#1##3...##4#1##5#1##6#1##7\skv@nil{%
    \skvifblankTF{##5}{%
      \skv@err{I can't find upper limit number or dimension,
        \MessageBreak i.e., after symbool '...'}\skv@ehd
    }{%
      % \skv@autocompletelist@b may be reentered. Hence
      \skviflacus{##1}\then\else
        \edef\skvcompletedlist{%
          \skvaddlist{#1}\skvcompletedlist
          \skvtrimspace{##1}%
        }%
      \fi
      \let\do\unexpanded
      \skvifblankTF{##3}{%
        \skvifblankTF{##4}{%
          \skv@err{No direction of growth before and/or after
            \MessageBreak symbol '...'}\skv@ehd
        }{%
          % Eg, {2pt_A,4pt_A,...pt_A,10pt_A}. Here ##3 is nil, grow left.
          \def\skv@autocomplete@growleft{00}%
          \def\skv@autocomplete@growright{01}%
          \skvexpanded{%
            \skv@autocompletelist@f
              {\do{#1}}{\do{##4}}{\do{##1}}{\do{##2}}{\do{##5}}%
          }%
        }%
      }{%
        \skvifblankTF{##4}{%
          % Eg, {A_2pt,A_4pt,A_...,A_10pt}. Here ##4 is nil, grow right.
          \def\skv@autocomplete@growright{00}%
          \def\skv@autocomplete@growleft{01}%
          \skvexpanded{%
            \skv@autocompletelist@f
              {\do{#1}}{\do{##3}}{\do{##1}}{\do{##2}}{\do{##5}}%
          }%
        }{%
          % Eg, {A_2pt,A_4pt,A_...pt,A_10pt}.
          \skvexpanded{%
            \skv@autocompletelist@g
              {\do{#1}}{\do{##3}}{\do{##4}}{\do{##1}}{\do{##2}}{\do{##5}}%
          }%
        }%
      }%
      % In case the list is folded on ellipsis (...):
      \skvifblankTF{##6}{}{\skv@autocompletelist@b{#1}{##6#1##7}}%
    }%
  }%
  \expandafter\skv@prova\skv@tempa#1#1#1\skv@nil
}
% \skv@autocompletelist@f
%       {&lt;parser&gt;}{&lt;guide&gt;}{&lt;lower1&gt;}{&lt;lower2&gt;}{&lt;upper&gt;}
%
% 1. Use the &lt;guide&gt; to get the constant and variable parts of the
%    elements.
% 2. Use the variable parts to determine if the list is Alpah, alpha or
%    number type. In this format, the unit in dimension type of list may
%    appear in &lt;guide&gt;.
% 3. Use the variable parts to work out the &lt;step&gt;.
% 4. Call the relevant macro to fill the list.
% 5. &lt;lower1&gt; has already been saved in \skvcompletedlist.
%
\skvrobustdef*\skv@autocompletelist@f#1#2#3#4#5{%
  \skv@checkguideinbounds{#2}{{#3}{#4}{#5}}%
  % Use the 'link' (#2) to get from {&lt;lower1&gt;}, {&lt;lower2&gt;} and {&lt;upper&gt;}
  % the left or right sides of the elements that should be grown:
  \def\skv@prova##1#2##2\skv@nil##3{%
    \edef##3{\if\skv@autocomplete@growleft##1\else##2\fi}%
  }%
  % &lt;lower1&gt; is empty when there is only one element before ellipsis:
  \skviflacus#3\then
    \def\skv@tempa{}%
  \else
    \skv@prova#3\skv@nil\skv@tempa
  \fi
  \skv@prova#4\skv@nil\skv@tempb
  \skv@prova#5\skv@nil\skv@tempc
  \let\do\skvexpandonce
  \skvexpandsecond
    {\skv@autocompletelist@h{#1}{#2}}%
    {{\do\skv@tempa}{\do\skv@tempb}{\do\skv@tempc}}%
}
% \skv@autocompletelist@g
%     {&lt;parser&gt;}{&lt;predots&gt;}{&lt;postdots&gt;}{&lt;lower1&gt;}{&lt;lower2&gt;}{&lt;upper&gt;}
\skvrobustdef*\skv@autocompletelist@g#1#2#3#4#5#6{%
  \def\skv@preandpostdotspresent{00}%
  \skv@checkguideinbounds{#2}{{#4}{#5}{#6}}%
  \skv@checkguideinbounds{#3}{{#4}{#5}{#6}}%
  % For &lt;lower1&gt;, &lt;lower2&gt; and &lt;upper&gt;, get the tokens between
  % &lt;predots&gt; and &lt;postdots&gt;. They are the ones to be grown.
  \def\skv@prova##1#2##2#3##3\skv@nil##4{%
    \edef##4{##2}%
  }%
  \ifx\@nnil#4\@nnil
    \let\skv@tempa\@empty
  \else
    \skv@prova#4\skv@nil\skv@tempa
  \fi
  \skv@prova#5\skv@nil\skv@tempb
  \skv@prova#6\skv@nil\skv@tempc
  % Pass &lt;guide&gt; as empty to \skv@autocompletelist@h. Through out, the only
  % reason for passing &lt;guide&gt; to \skv@autocompletelist@h is to restore
  % it in \skv@autocomplete@restore. But while
  % \skv@preandpostdotspresent is true, we won't do anything in
  % \skv@autocomplete@restore.
  \skvexpandsecond
    {\skv@autocompletelist@h{#1}{}}%
    {{\skv@tempa}{\skv@tempb}{\skv@tempc}}%
  % Restore &lt;predots&gt; and &lt;postdots&gt;:
  \def\do##1#1{%
    \ifx\do##1\else
      \edef\skvcompletedlist{%
        \skvaddlist{#1}\skvcompletedlist
        \unexpanded{#2}##1\unexpanded{#3}\skv@autocomplete@origunit
      }%
      \expandafter\do
    \fi
  }%
  \expandafter\do\skv@completedlist@partial#1\do#1%
}
% \skv@autocompletelist@h{&lt;parser&gt;}{&lt;guide&gt;}{&lt;lower1&gt;}{&lt;lower2&gt;}{&lt;upper&gt;}
%
% 1. Use the variable parts to determine if the list is Alpah, alpha or
%    number type. In this format, the unit in dimension type of list may
%    appear in &lt;guide&gt;.
% 2. Use the variable parts to work out the &lt;step&gt;.
% 3. Call the relevant macro to fill the list.
% 4. &lt;lower1&gt; has already been saved in \skvcompletedlist.
%
\skvrobustdef*\skv@autocompletelist@h#1#2#3#4#5{%
  \def\skv@completedlist@partial{}%
  \edef\skv@lowerlower{\ifx\@nnil#3\@nnil\else\unexpanded{#3}, \fi}%
  \skvifloweralpha{#4}{%
    \skv@foreach@swatrue
    \ifx\@nnil#3\@nnil\else
      \skvifloweralpha{#3}{}\skv@foreach@swafalse
    \fi
    \skvifloweralpha{#5}{}\skv@foreach@swafalse
    \ifskv@foreach@swa
      \ifx\@nnil#3\@nnil
        \def\skv@autocomplete@step{1}%
      \else
        \edef\skv@autocomplete@step{\the\numexpr\lccode`#4-\lccode`#3}%
        \ifnum\skv@autocomplete@step=\skvz@
          \def\skv@autocomplete@step{1}%
          \skv@autocomplete@zerostepwarn{#3}{#4}{}%
        \fi
      \fi
      \def\skv@isupperalpha{01}%
      % \skv@autocomplete@origunit remains nil on this branch.
      \skv@autocomplete@fillalphabetic{#1}{#4}{#5}\skv@completedlist@partial
      % Also update the items already entered in \skvcompletedlist.
      \skv@autocomplete@restore{#1}{#2}\skv@completedlist@partial
    \else
      \skv@err{The tokens '\detokenize\expandafter{\skv@lowerlower#4, #5}'
        \MessageBreak aren't of the same type}\skv@ehd
    \fi
  }{%
    \skvifupperalpha{#4}{%
      \skv@foreach@swatrue
      \ifx\@nnil#3\@nnil\else
        \skvifupperalpha{#3}{}\skv@foreach@swafalse
      \fi
      \skvifupperalpha{#5}{}\skv@foreach@swafalse
      \ifskv@foreach@swa
        \ifx\@nnil#3\@nnil
          \def\skv@autocomplete@step{1}%
        \else
          \edef\skv@autocomplete@step{\the\numexpr\uccode`#4-\uccode`#3}%
          \ifnum\skv@autocomplete@step=\skvz@
            \def\skv@autocomplete@step{1}%
            \skv@autocomplete@zerostepwarn{#3}{#4}{}%
          \fi
        \fi
        \def\skv@isupperalpha{00}%
        % \skv@autocomplete@origunit remains nil on this branch.
        \skv@autocomplete@fillalphabetic{#1}{#4}{#5}\skv@completedlist@partial
        \skv@autocomplete@restore{#1}{#2}\skv@completedlist@partial
      \else
        \skv@err{The tokens '\detokenize\expandafter{\skv@lowerlower#4, #5}'
          \MessageBreak aren't of the same type}\skv@ehd
      \fi
    }{%
      \skv@foreach@swatrue
      \ifx\@nnil#3\@nnil\else
        \skvifdimensionable{#3}{}\skv@foreach@swafalse
      \fi
      \skvifdimensionable{#4}{}\skv@foreach@swafalse
      \let\skv@autocomplete@origunit\skv@dimunit
      \skvifdimensionable{#5}{}\skv@foreach@swafalse
      \ifx\skv@autocomplete@origunit\skv@dimunit\else
        \skv@err{The units on \detokenize{'#4', '#5'} are different}\skv@ehd
      \fi
      \ifskv@foreach@swa
        \ifx\@nnil#3\@nnil
          \def\skv@autocomplete@step{1pt}%
        \else
          \edef\skv@autocomplete@step{\the\dimexpr#4-#3\relax}%
          \ifdim\skv@autocomplete@step=\skvz@
            \def\skv@autocomplete@step{1pt}%
            \skv@autocomplete@zerostepwarn{#3}{#4}{pt}%
          \fi
        \fi
        \skvexpandsecond
          {\skv@autocomplete@fillnumordim{#1}}{{#4}{#5}}%
          \skv@completedlist@partial
        \skv@autocomplete@strippoint{#1}\skv@completedlist@partial
        % Attach the constant part to the elements of the completed list.
        % &lt;lower1&gt; was saved earlier in \skv@autocompletelist@e, and
        % &lt;lower2&gt; and &lt;upper&gt; have been saved while filling the list.
        % Always strip point and restore original unit here.
        \skv@autocomplete@restore{#1}{#2}\skv@completedlist@partial
      \else
        \skv@foreach@swatrue
        \ifx\@nnil#3\@nnil\else
          \skvifdimensionable{#3pt}{}\skv@foreach@swafalse
        \fi
        \skvifdimensionable{#4pt}{}\skv@foreach@swafalse
        \skvifdimensionable{#5pt}{}\skv@foreach@swafalse
        \ifskv@foreach@swa
          \ifx\@nnil#3\@nnil
            \def\skv@autocomplete@step{1pt}%
          \else
            \edef\skv@autocomplete@step{\the\dimexpr#4pt-#3pt\relax}%
            \ifdim\skv@autocomplete@step=\skvz@
              \def\skv@autocomplete@step{1pt}%
              \skv@autocomplete@zerostepwarn{#3}{#4}{pt}%
            \fi
          \fi
          % \skv@autocomplete@origunit remains nil on this branch.
          \skvexpandsecondonce
            {\skv@autocomplete@fillnumordim{#1}}{{#4pt}{#5pt}}%
            \skv@completedlist@partial
          \skv@autocomplete@strippoint{#1}\skv@completedlist@partial
          \skv@autocomplete@restore{#1}{#2}\skv@completedlist@partial
        \else
          \skv@err{Sorry, the tokens
            '\detokenize\expandafter{\skv@lowerlower#4, #5}'
            \MessageBreak are unparsable. I have given up on them.
            \MessageBreak Did you miss something syntactic?
            \MessageBreak See manual for acceptable syntaxes}\skv@ehd
        \fi
      \fi
    }%
  }%
}
% \skv@autocomplete@fillnumordim&lt;parser&gt;&lt;lower&gt;&lt;upper&gt;&lt;listcmd&gt;
\skvrobustdef*\skv@autocomplete@fillnumordim#1#2#3#4{%
  \begingroup
  \skv@autocomplete@getcomparator
  \if\skv@autocomplete@stepisneg
    \ifdim#3\skv@autocomplete@unit&gt;#2\skv@autocomplete@unit\relax
      \skv@err{Step '\skv@autocomplete@step' is negative but upperbound
        \MessageBreak '\detokenize{#3}' is greater than lowerbound
        '\detokenize{#2}'}\skv@ehd
    \fi
  \else
    \ifdim#3\skv@autocomplete@unit&lt;#2\skv@autocomplete@unit\relax
      \skv@err{Step '\skv@autocomplete@step' is nonnegative but upperbound
        \MessageBreak '\detokenize{#3}' is less than lowerbound
        '\detokenize{#2}'}\skv@ehd
    \fi
  \fi
  % The bounds may have decimal places. So the calculation has to be
  % done with \dimexpr:
  \edef\skv@upperlimit{\the\dimexpr#3\skv@autocomplete@unit}%
  \edef\skv@lowerlimit{\the\dimexpr#2\skv@autocomplete@unit}%
  \skv@autocomplete@addtolist{#1}\skv@lowerlimit#4%
  \ifdim\skv@lowerlimit\skv@comparator\skv@upperlimit\relax
    \def\do{%
      \edef\skv@lowerlimit{%
        \the\dimexpr\skv@lowerlimit
        +\skv@autocomplete@step\skv@autocomplete@unit\relax
      }%
      \ifdim\skv@lowerlimit\skv@comparator\skv@upperlimit\relax
        \skv@autocomplete@addtolist{#1}\skv@lowerlimit#4%
        \expandafter\do
      \fi
    }%
    \do
    % The last item has to in 'pt', so that 'pt' can be stripped.
    % Hence \dimexpr.
    \skv@autocomplete@addtolist{#1}\skv@upperlimit#4%
  \fi
  \skvaftergroupdef#4\endgroup
}
% Fill Alpha or alpha.
% \skv@autocomplete@fillalphabetic&lt;parser&gt;&lt;lower&gt;&lt;upper&gt;&lt;listcmd&gt;
\skvrobustdef*\skv@autocomplete@fillalphabetic#1#2#3#4{%
  \begingroup
  \def\skv@inalphabetic{00}%
  \skv@autocomplete@getcomparator
  \edef\skv@type{%
    \if\skv@isupperalpha Upper\else Lower\fi case alphabetic%
  }%
  \edef\reserved@a{\if-\skv@autocomplete@step\else\skv@autocomplete@step\fi}%
  \skvoifinteger\reserved@a{}{%
    \skv@err{List is '\skv@type' type but\MessageBreak
      step '\skv@autocomplete@step' isn't an integer}\skv@ehd
  }%
  \skv@autocomplete@addtolist{#1}{#2}#4%
  \skvifstrcmpTF{#2}{#3}{}{%
    \edef\skv@lowerlimit{#2}%
    \edef\skv@upperlimit{#3}%
    \skvexpandnext{\chardef\skv@lowerlimit`}\skv@lowerlimit\relax
    \skvexpandnext{\chardef\skv@upperlimit`}\skv@upperlimit\relax
    \edef\skv@lowerlimit{%
      \the\numexpr\skv@lowerlimit-\if\skv@isupperalpha 64\else 96\fi
    }%
    \edef\skv@upperlimit{%
      \the\numexpr\skv@upperlimit-\if\skv@isupperalpha 64\else 96\fi
    }%
    \edef\skv@charcase{\the\numexpr\skv@lowerlimit+\skv@autocomplete@step}%
    \skvrecurse
      \if\skv@isupperalpha
        \edef\skv@tempa{\skv@ucalpha\skv@charcase}%
      \else
        \edef\skv@tempa{\skv@lcalpha\skv@charcase}%
      \fi
      \skv@autocomplete@addtolist{#1}\skv@tempa#4%
      \edef\skv@charcase{\the\numexpr\skv@charcase+\skv@autocomplete@step}%
    \while
      \ifnum\skv@charcase\skv@comparator\skv@upperlimit\relax
    \fi
    \skv@autocomplete@addtolist{#1}{#3}#4%
  }%
  \skvaftergroupdef#4\endgroup
}
%
% \skv@autocomplete@splitbeforedots{&lt;parser&gt;}{&lt;list&gt;}
%
% Get the one or two elements before '...' or before '&lt;guide&gt;,...'.
%
%    {A_2pt,A_4pt,A_...pt,A_10pt} : no additional info. required
%    {a^1,a^3,a^...,a^9}          : no additional info. required
%    {A_1,B_1,..._1,E_1}          : no additional info. required
%    {1--,4--,...--,16--}         : no additional info. required
%    {1pt,4pt,...pt,10pt}         : no additional info. required
%    {A_2pt,A_4pt,A_...,A_10pt}   : no additional info. required
%
%    {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 no addit. info.
%    {A_2pt,A_4pt,...,A_10pt}     : link = _,   grow = right
%
% The items prior to the two before '&lt;guide&gt;...' or before '...'
% are called 'all-before-the-two' (AB2). Collect in \skv@tempa the two
% items before '&lt;guide&gt;...' or before '...' together with the rest of the
% list. Save the AB2 items in \skvcompletedlist.
%
% Return \skvcompletedlist and \skv@tempa.
%
\skvrobustdef*\skv@autocomplete@splitbeforedots#1#2{%
  % First count all the elements before '&lt;guide&gt;&lt;parser&gt;...' or '...'.
  % We're already sure that argument #2 contains '&lt;guide&gt;&lt;parser&gt;...'
  % or '...'. \skvcompletedlist has been initialized before here.
  \begingroup
  \skv@cnta\skvz@
  \def\do##1#1{%
    \skvifinTF{...}{##1}{%
      % Gobble the rest:
      \def\do####1\skv@nil{}%
    }{%
      \advance\skv@cnta\@ne
    }%
    \do
  }%
  \do#2#1\skv@nil
  \ifnum\skv@cnta&gt;\tw@
    \@tempcnta\m@ne
    \def\do##1#1{%
      \advance\@tempcnta\@ne
      \ifnum\@tempcnta=\numexpr\skv@cnta-\tw@\relax
        \def\do####1\skv@nil{\def\skv@tempa{##1#1####1}}%
      \else
        \edef\skvcompletedlist{%
          \skvaddlist{#1}\skvcompletedlist\unexpanded{##1}%
        }%
      \fi
      \do
    }%
    \do#2#1\skv@nil
  \else
    \ifnum\skv@cnta=\@ne
      % There is only one element before '&lt;guide&gt;&lt;parser&gt;...' or '...'.
      % Hence simply left-pad argument #2 with &lt;parser&gt; to give the
      % impression of at least 2 elements:
      \def\skv@tempa{#1#2}%
    \else
      \ifnum\skv@cnta=\tw@
        \def\skv@tempa{#2}%
      \else
        \ifnum\skv@cnta=\skvz@
          \skv@err{List &lt;&lt;\detokenize{#2}&gt;&gt;\MessageBreak
            contains symbol '...' but not a lowerbound}\skv@ehd
        \fi
      \fi
    \fi
  \fi
  \skvexpanded{\endgroup
    \skvcmdexit\skvcompletedlist\skvcmdexit\skv@tempa
  }%
}
% \skv@autocomplete@splitandgrow{&lt;parser&gt;}{&lt;lower1&gt;}{&lt;lower2&gt;}{&lt;upperbound&gt;}
%
%    {0\pi,0.5\pi,...,3\pi} : link = \pi ; grow left
%    {1--,4--,...,10--}     : link = --  ; grow left
%    {2pt,4pt,...,10pt}     : link = pt  ; grow left (or no additional info.)
%    {A_1,C_1,...,Q_1}      : link = _   ; grow left
%    {2^a,2^c,...,2^q}      : link = ^   ; grow right
%
% 1. Providing the link avoids the need to use the syntax of PGF's
%    \foreach, such as {0\pi,0.5\pi,...\pi,3\pi}. But skeyval can also
%    autocomplete lists like {0\pi,0.5\pi,...\pi,3\pi}.
% 2. We already know that the key 'link' will reject empty values.
%
\skvrobustdef*\skv@autocomplete@splitandgrow#1#2#3#4{%
  \ifx\skv@autocomplete@growleft\skv@autocomplete@growright
    \skv@err{I can't grow the list in both directions.
      \MessageBreak Maybe you haven't indicated the
      \MessageBreak direction of growth (left or right),
      \MessageBreak or both directions are 'true'.}
      {Try one of the keys 'grow=left or right',
      \MessageBreak 'grow left=true or false',
      'grow right=true or false'}\skv@ehd
  \fi
  \begingroup
  \def\skv@prova##1{%
    \skv@foreach@swatrue
    \skviflacus#2\then\else
      \skvifinTF{##1}{#2}{}\skv@foreach@swafalse
    \fi
    \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
        '\detokenize\expandafter{\skv@provb#3, #4}'}\skv@ehd
    \fi
    \def\skv@prova####1##1####2\skv@nil{%
      \if\skv@autocomplete@growright
        \edef\skv@prova{\skvtrimspace{####1##1}}%
      \else
        \edef\skv@prova{\skvtrimspace{##1####2}}%
      \fi
      \def\do########1{{\skvtrimspace{########1}}}%
      % \skv@autocompletelist@f&lt;parser&gt;&lt;guide&gt;&lt;lower1&gt;&lt;lower2&gt;&lt;upper&gt;
      \skvexpanded{\endgroup
        \noexpand\skv@autocompletelist@f
        {\unexpanded{#1}}{\skvexpandonce\skv@prova}\do{#2}\do{#3}\do{#4}%
      }%
    }%
    \skv@prova#3\skv@nil
  }%
  \expandafter\skv@prova\expandafter{\skv@autocomplete@link}%
}
\skvrobustdef*\skv@autocomplete@getcomparator{%
  \begingroup
  % &lt;unit&gt; isn't required in alphabetic sequences:
  \if\skv@inalphabetic\else
    \let\skvreversedo\@iden
    \edef\skv@provb{\skvexpbracenext\skvreverse\skv@autocomplete@step}%
    \def\skv@prova##1##2##3\skv@nil{%
      \skvxifinTF{,\detokenize{##2##1},}{,\skvoxdetok\skv@validunit,}{%
        % That is, the sequence is made up of dimensions.
        \def\skv@autocomplete@unit{}%
      }{%
        \def\skv@autocomplete@unit{pt}%
      }%
    }%
    \expandafter\skv@prova\skv@provb\skv@nil
  \fi
  % You can't use \ifnum or \ifdim here, since for alphanumeric sequences
  % \skv@autocomplete@step isn't a dimension.
  \def\skv@prova##1##2\skv@nil{%
    \edef\skv@autocomplete@stepisneg{0\if-##10\else1\fi}%
  }%
  \expandafter\skv@prova\skv@autocomplete@step\skv@nil
  \edef\skv@comparator{\if\skv@autocomplete@stepisneg&gt;\else&lt;\fi}%
  \let\do\skvcmdexit
  \skvexpanded{\endgroup
    \do\skv@autocomplete@stepisneg\do\skv@comparator
    \if\skv@inalphabetic\else\do\skv@autocomplete@unit\fi
  }%
}
\begingroup
\catcode`P=12 \lccode`P=112
\catcode`T=12 \lccode`T=116
\lowercase{\endgroup
  \def\skv@autocomplete@strippoint#1#2{%
    \def\reserved@a##1#1\relax{\def#2{##1}}%
    \def\do##1.##2PT#1{%
      \ifx\do##1\else##1%
        \if\skv@autocomplete@keephighdecimals
          \ifdim.##2pt&gt;.5pt\relax##2\fi
        \else
          \if\skv@autocomplete@keepdecimals
            \ifnum##2&gt;\skvz@.##2\fi
          \fi
        \fi
        \unexpanded{#1}%
        \expandafter\do
      \fi
    }%
    \edef#2{\expandafter\do#2#1\do.PT#1}%
    \expandafter\reserved@a#2\relax
  }
}
% \skv@autocomplete@restore{&lt;parser&gt;}{&lt;guide&gt;}{&lt;listcmd&gt;}
%
% Restore guide and, in the case of dimension sequences, 'original unit'.
%
\skvrobustdef*\skv@autocomplete@restore#1#2#3{%
  \if\skv@preandpostdotspresent
    % Leave it: &lt;predots&gt; and &lt;postdots&gt; will be restored in
    % \skv@autocompletelist@g.
  \else
    \def\do##1#1{%
      \ifx\do##1\else
        \edef\skvcompletedlist{%
          \skvaddlist{#1}\skvcompletedlist
          \if\skv@autocomplete@growleft
            ##1\skv@autocomplete@origunit\unexpanded{#2}%
          \else
            \unexpanded{#2}##1\skv@autocomplete@origunit
          \fi
        }%
        \expandafter\do
      \fi
    }%
    \expandafter\do#3#1\do#1%
  \fi
}


\skv@for@restorecatcodes
\endinput
</pre></body></html>