summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/etextools
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex/contrib/etextools
Initial commit
Diffstat (limited to 'macros/latex/contrib/etextools')
-rw-r--r--macros/latex/contrib/etextools/README26
-rw-r--r--macros/latex/contrib/etextools/etextools-examples.pdfbin0 -> 111229 bytes
-rw-r--r--macros/latex/contrib/etextools/etextools-examples.tex304
-rw-r--r--macros/latex/contrib/etextools/etextools.dtx5429
-rw-r--r--macros/latex/contrib/etextools/etextools.pdfbin0 -> 1124995 bytes
5 files changed, 5759 insertions, 0 deletions
diff --git a/macros/latex/contrib/etextools/README b/macros/latex/contrib/etextools/README
new file mode 100644
index 0000000000..7274a965d8
--- /dev/null
+++ b/macros/latex/contrib/etextools/README
@@ -0,0 +1,26 @@
+% etextools v3.14159 (stable) - 2010/04/20
+% This work consists of the main source file etextools.dtx
+% and the derived files
+% etextools.sty, etextools.pdf, etextools.ins,
+% etextools-examples.tex
+% Unpacking:
+% (a) If etextools.ins is present:
+% etex etextools.ins
+% (b) Without etextools.ins:
+% etex etextools.dtx
+% (c) If you insist on using LaTeX
+% latex \let\install=y\input{etextools.dtx}
+% (quote the arguments according to the demands of your shell)
+% Documentation: (pdf)latex etextools.dtx; ...
+% -----------------------------------------------------------------------------------------
+etextools provides many (purely expandable) tools for LaTeX:
+- Extensive list management (csv lists, lists of single tokens/characters, etoolbox lists):
+ . purely expandable loops (csvloop, forcsvloop etc.)
+ . conversion (csvtolist etc.))
+ . addition/deletion (csvadd, listdel etc.)
+- Expansion and groups control : \expandnext, \ExpandAfterCmds, \AfterGroup...
+- Tests on tokens, characters and control sequences (\iffirstchar, \ifiscs, \ifdefcount, \@ifchar...)
+- Tests on strings (\ifstrnum, \ifuppercase, \DeclareStringFilter...)
+- Purely expandable macros with options (\FE@testopt, \FE@ifstar) or modifiers (\FE@modifiers)
+- Some purely expandable numerics (\interval, \locinterplin)
+% -----------------------------------------------------------------------------------------
diff --git a/macros/latex/contrib/etextools/etextools-examples.pdf b/macros/latex/contrib/etextools/etextools-examples.pdf
new file mode 100644
index 0000000000..b104130aa2
--- /dev/null
+++ b/macros/latex/contrib/etextools/etextools-examples.pdf
Binary files differ
diff --git a/macros/latex/contrib/etextools/etextools-examples.tex b/macros/latex/contrib/etextools/etextools-examples.tex
new file mode 100644
index 0000000000..dca5845584
--- /dev/null
+++ b/macros/latex/contrib/etextools/etextools-examples.tex
@@ -0,0 +1,304 @@
+%%
+%% This is file `etextools-examples.tex',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% etextools.dtx (with options: `example')
+%%
+%% This is a generated file.
+%%
+%% This work may be distributed and/or modified under the
+%% conditions of the LaTeX Project Public License, either
+%% version 1.3 of this license or (at your option) any later
+%% version. The latest version of this license is in
+%% http://www.latex-project.org/lppl.txt
+%%
+%% This work consists of the main source file etextools.dtx
+%% and the derived files
+%% etextools.sty, etextools.pdf, etextools.ins,
+%% and etextools-examples.tex
+%%
+\ProvidesFile{etextools-examples}
+\documentclass[11pt,french,a4paper,oneside]{scrartcl}
+\usepackage[latin1]{inputenc}
+\usepackage[T1]{fontenc}
+\usepackage[american]{babel}
+\usepackage{geometry,doc,ltxdockit,txfonts,fancyhdr,stmaryrd,graphicx,enumitem}
+\usepackage{etextools}
+\usepackage{fancyvrb}
+\makeatletter
+\let\org@newif\newif
+\def\newif#1{\ifx#1\ifnotempty\else\expandafter\org@newif\fi}
+\usepackage{umrand}
+\renewcommand\ifne[1]{\csname @\ifcat $\detokenize{#1}$first\else second\fi oftwo\endcsname\iffalse\iftrue}
+\let\newif\org@newif
+\font\umranda=umranda \def\Ch{\char'}
+\def\textvb#1{{\usefont{T1}{txtt}{m}{n}#1}}
+\newrobustcmd\thispackage{\xpackage{\spot etextools}\xspace}
+\newrobustcmd\xpackage[1]{{\usefont{T1}{lmss}{bx}{n}\db\mbox{#1}}}
+\hypersetup{colorlinks,pdfstartview={FitH}}
+\geometry{top=1.5cm,bottom=1.2cm,left=2.5cm,right=1cm}
+\fancyhf{}
+\fancyhead[L]{Examples for the \thispackage package}
+\pagestyle{fancy}
+\DefineShortVerb{\|}
+\catcode`\^^a7 \active\def^^a7{\par\nobreak\vskip-\parskip}
+\DefineVerbatimEnvironment{VerbLines}{Verbatim}
+ {gobble=1,commandchars=!(),frame=lines,framesep=6pt,fontfamily=txtt,fontseries=m}
+\apptocmd\@list@extra{\parsep\parskip\topsep\z@\itemsep\z@}{}{}
+\def\smex{\leavevmode\hb@xt@2em{\hfil$\longrightarrow$\hfil}}
+\def\FE{\setbox8\hbox{$\m@th\bindnasrepma$}%
+ \textcolor{fecc}{\scalebox{2}{$\copy8\mkern-13.5mu\copy8\mkern-13.5mu\copy8$}}}
+\def\pdfFE{\setbox8\hbox{$\m@th\bindnasrepma$}%
+ \textcolor{fecc}{\llap{\textsf{pdf}\TeX{}\,}\scalebox{2}{$\copy8\mkern-13.5mu\copy8\mkern-13.5mu\copy8$}}}
+\definecolor{fecc}{rgb}{.2,.6,.2}
+\definecolor{dg}{rgb}{0.00,0.37,0.00} \newrobustcmd\dg{\color{dg}} \newrobustcmd\dgbf{\dg\bfseries}
+\definecolor{spot}{rgb}{1.00,0.33,0.00} \newrobustcmd\spot{\color{spot}}
+\definecolor{db}{rgb}{0.00,0.00,0.25} \newrobustcmd\db{\color{db}}
+\newrobustcmd\blue{\color{blue}}
+\newrobustcmd\nnn{\normalfont\mdseries\upshape}
+\newrobustcmd\ClearPage{\@ifstar\clearpage{}}
+\def\make@macro#1{\string\def\string#1\parameters@meaning#1\string{\strip@meaning#1\string}}
+\newcommand\preline{\@ifstar{\@preline}{\hrulefill\par\@preline}}
+\newcommand\@preline[2][1.5ex]{\noindent\hskip6pt\textvb{\make@macro#2}\par\ifblank{#1}{}{\vskip#1}}
+\ifdef\pdfstrcmp{\let\ifpdfTeX\iffalse}{\let\ifpdfTeX\iftrue}
+\newcommand*\test{\@ifstar{\let\fe\pdfFE\testi}{\let\fe\FE\testi}}
+\newcommand\testi[1]{%
+ \csname test#1\endcsname
+ \edef\usercmd{\strip@meaningcs{test#1}}\edef\result{\meaningcs{#1Test}}\noindent
+ \begin{tabular}{lp{15cm}}
+ \multicolumn{2}{l}{\textcolor{blue}{\llap{\fe\,\smex}\tt \usercmd}} \\[1.5ex]
+ \cmd{#1Test}= & \tt\bfseries\result
+ \end{tabular}\par\nobreak\hrulefill\null\goodbreak}
+\begin{document}
+\title{\vskip-2cm\thispackage\ examples}
+\subtitle{Examples for some macros provided by the \thispackage package}
+\author{\small<FC -- December 12, 2010>}
+\date{}
+\newsavebox\helpbox \newsavebox\helpboxx
+\newrobustcmd*\mydotleader[2][\z@]{\leavevmode\xleaders\hbox to\dimexpr1.7pt+#1{\hss\raise#2\hbox{$\scriptscriptstyle\cdotp$}\hss}}
+\begingroup\let\clearpage\@empty
+\setbox\helpbox\hbox to13cm{\hss\lower3cm\vbox to1.8cm{\maketitle\vss}\hss}
+\fboxsep\z@
+\newrobustcmd\corner[2][\spot\umranda]{\hbox{#1\rlap{\char'115}\char'#2}}
+\null\vskip-1cm\hskip-1cm\null\hfil\RandBox {\fbox{\copy\helpbox}}
+ font {\umranda} [0pt]
+ (\corner{17}) ([\Ch111]) (\corner{14})
+ ([\Ch112]) ([\Ch112])
+ (\corner{21}) ([\Ch111]) (\corner{11})
+\endgroup
+\tableofcontents\hyperdef{ettlex}{toc}{}
+\section{\cmd{expandnext} examples}
+\subsection{Test if the replacement text of macro is really empty}
+\def\xx{ }
+\def\testexpandnext{%
+ \edef\expandnextTest{\string\xx\ is \expandnext\ifempty{\xx}{}{not} empty}
+}
+\preline\xx
+\test{expandnext}
+\def\xx{}
+\preline\xx
+\test{expandnext}
+\ClearPage*
+\subsection{Test if the replacement text of a macro is blank (empty or spaces)}
+\def\xx{something}
+\def\testexpandnext{%
+ \edef\expandnextTest{\string\xx\ is \expandnext\ifblank{\xx}{}{not} blank}
+}
+\preline\xx
+\test{expandnext}
+\def\xx{ }
+\preline\xx
+\test{expandnext}
+\section{\cmd{ExpandNext} examples}
+Example of the main documentation file to reverse the order of the characters in a string:
+\def\swap#1#2{{#2#1}} \def\do[#1]#2{\swap #2}% \do{abcdef} -> \swap ab + cdef -> {ba}cdef
+ % \do{{ba}cdef} -> \swap {ba}c + def -> {cba}def
+\edef\result{\naturalloop[\do]{4}{12345}}
+\ExpandNext{\def\RESULT}{\naturalloop[\do]{4}{12345}}
+\begin{VerbLines}
+\def\swap#1#2{{#2#1}} \def\do[#1]#2{\swap #2}
+\edef\result{\naturalloop[\do]{4}{12345}}
+\meaning\result = !bfseries!meaning!result
+\ExpandNext{\def\RESULT}{\naturalloop[\do]{4}{12345}}
+\meaning\RESULT = !bfseries!meaning!RESULT
+\end{VerbLines}
+\subsection{Test the parameter string of a macro}
+The following commands create the filter for the string: "\textvb{[\#1]\#2"}":^^a7
+\begin{VerbLines}[commandchars=!()]
+\ExpandNext{(!blue\DeclareStringFilter\ParaFilt)}
+ {\ExpandAftercmds\@gobblescape{\expandafter\string\csname(!blue[#1]#2)\endcsname}}
+\end{VerbLines}
+\ExpandNext{\DeclareStringFilter\ParaFilt}
+ {\ExpandAftercmds\@gobblescape{\expandafter\string\csname[#1]#2\endcsname}}
+\begin{enumerate}[label=\arabic*)~,noitemsep,nolistsep]
+\item |\csname[#1]#2\endcsname| is expanded first
+\item Immediately after: |\string|
+\item At this stage: |\[#1]#2| (everything in category code other) is no more expandable
+\item Then |\ExpandAftercmds| expands |\@gobblescape|
+\item |[#1]#2| is no more expandable
+\item Then |\ExpandNext| expands its first argument: |\DeclareStringFilter\ParaFilt{[#1]#2}|
+\end{enumerate}
+Remark: |\detokenize| would have doubled the \# characters. Another possibility is to temporarily change the
+category code of \# to 12 (other):
+\begin{VerbLines}[commandchars=!()]
+\begingroup\catcode`\#=12
+ (!blue\DeclareStringFilter\ParaFilt{[#1]#2}) !nnn global declaration
+\endgroup
+\end{VerbLines}
+\def\macroA#1#2{Something to do with #1 and #2}
+\def\macroB[#1]#2{Something to do with #1 and #2}
+\preline[]\macroA
+\preline*[]\macroB
+\begin{Verbatim}[commandchars=!()]
+ !blue\ExpandNext{\ParaFilt=.}{\parameters@meaning\macroA}{macro complies with [\#1]\#2}
+ !blue{macro does not comply }
+\end{Verbatim}
+\hfill\textvb{\dgbf\ExpandNext{\ParaFilt=.}{\parameters@meaning\macroA}{macro complies with [\#1]\#2}
+ {macro does not comply }}
+\begin{Verbatim}[commandchars=!()]
+ !blue\ExpandNext{\ParaFilt=.}{\parameters@meaning\macroB}{macro complies with [\#1]\#2}
+ !blue{macro does not comply }
+\end{Verbatim}
+\hfill\textvb{\dgbf\ExpandNext{\ParaFilt=.}{\parameters@meaning\macroB}{macro complies with [\#1]\#2}
+ {macro does not comply }}
+\par\hrulefill\par
+\ClearPage*
+\section{Testing characters}
+\subsection{\cmd{ifsinglechar} versus \cmd{iffirstchar}}
+\def\testifsinglechar{%
+ \edef\ifsinglecharTest{\ifsinglechar *{*hello*}{ single star }{ something else }}
+}\hrulefill\par
+\test{ifsinglechar}
+\def\testifsinglechar{%
+ \edef\ifsinglecharTest{\ifsinglechar *{ *}{ single star }{ something else }}
+}\hrulefill\par
+\test{ifsinglechar}
+\def\testifsinglechar{%
+ \edef\ifsinglecharTest{\ifsinglechar *{ * }{ single star }{ something else }}
+}\hrulefill\par
+\test{ifsinglechar}
+{\small Note the space \textbf{after} the star $\uparrow$.}
+\def\testiffirstchar{%
+ \edef\iffirstcharTest{\iffirstchar *{*hello*}{ first char is star }{ something else }}
+}\hrulefill\par
+\test{iffirstchar}
+\subsection{Fully Expandable starred macros}
+\def\starmacro#1{\FE@ifstar{#1}\starred\notstarred}
+\def\starred#1{your "#1" will be processed by the STAR form}
+\def\notstarred#1{your "#1" will be processed by the NORMAL form}
+\def\testFE@ifstar{%
+ \edef\FE@ifstarTest{\starmacro{sample text}}}
+\preline\starmacro
+\preline*\starred
+\preline*\notstarred
+\test{FE@ifstar}
+\def\testFE@ifstar{%
+ \edef\FE@ifstarTest{\starmacro*{sample text}}}
+\hrulefill\par
+\test{FE@ifstar}
+\subsection{Fully Expandable macros with options}
+\def\optmacro#1{\FE@testopt{#1}\OPTmacro{Mr.}}
+\def\OPTmacro[#1]#2{#1 #2}
+\def\testFE@testopt{%
+ \edef\FE@testoptTest{\optmacro{Woody Allen}}}
+\preline\optmacro
+\preline*\OPTmacro
+\test{FE@testopt}
+\def\testFE@testopt{%
+ \edef\FE@testoptTest{\optmacro[Ms.]{Vanessa Paradis}}}
+\hrulefill\par
+\test{FE@testopt}
+\ClearPage*
+\section{Lists management}
+\subsection{\cmd{csvloop} and \cmd{csvloop*} examples}
+\subsubsection{\cmd{makequotes}}
+\def\makequotes#1{"#1"\space}
+\def\testcsvloop{%
+ \edef\csvloopTest{\csvloop*[\makequotes]{hello,world}}
+}
+\preline\makequotes
+\test{csvloop}
+\subsubsection{\cmd{detokenize}}
+\def\testcsvloop{%
+ \edef\csvloopTest{\csvloop*[\detokenize]{\un,\deux}}
+}\hrulefill\par
+\test{csvloop}
+\subsubsection{\cmd{numexpr}}
+\def\mylist{1,2,3,4,5}\def\BySeven#1{$#1\times 7 = \number\numexpr#1*7\relax$\par}
+\def\testcsvloop{%
+ \edef\csvloopTest{\csvloop[\BySeven]\mylist}}
+\preline\mylist
+\preline*\BySeven
+\test{csvloop}
+\subsubsection{protected \cmd{textbf}}
+\def\testcsvloop{%
+ \protected@edef\csvloopTest{\csvloop*[\textbf]{hello ,my ,friends}}
+}\hrulefill\par
+\test{csvloop}
+\subsection{Index in lists and items by index}
+\subsubsection{\cmd{listloop}: getting specific item}
+\csvtolist*[\mylist]{one,two,three,four,five,alpha,beta,gamma}
+\def\testgetlistitem{%
+ \edef\getlistitemTest{\listloop[4]\mylist}
+}\hrulefill\par
+\noindent\hskip6pt|\csvtolist*[\mylist]{one,two,three,four,five,alpha,beta,gamma}|\par\vskip1.5ex
+\test{getlistitem}
+\ClearPage*
+\subsubsection{\cmd{getlistindex}}
+\ifpdfTeX
+\leavevmode\vadjust{\textsl{Require the }\string\pdfstrcmp\ \textsl{primitive (pdf\TeX{}) :}}
+\def\testgetlistindex{%
+ \edef\getlistindexTest{\getlistindex{alpha}\mylist}
+}\hrulefill\par
+\noindent\hskip6pt|\csvtolist*[\mylist]{one,two,three,four,five,alpha,beta,gamma}|\par\vskip1.5ex
+\test*{getlistindex}
+\leavevmode\vadjust{\textsl{Require the }\string\pdfstrcmp\ \textsl{primitive (pdf\TeX{}) :}}
+\def\testgetlistindex{%
+ \edef\getlistindexTest{\getcsvlistindex*{alpha}{one,two,three,four,five,alpha,beta}}
+}\hrulefill\par
+\test*{getlistindex}
+\fi
+\hrulefill\par
+\getlistindex[\myindex]{alpha}\mylist
+{\color{blue}\noindent\hskip6pt\llap\smex|\getlistindex[\myindex]{alpha}\mylist|\par\vskip1.5ex}
+{\tt\string\myindex=\quad\textbf{\meaning\myindex}}
+\par\hrulefill\par\vskip.5ex
+\hrulefill\par
+\newcount\myindex
+\getcsvlistindex*[\myindex]{alpha}{one,two,three,four,five,alpha,beta}
+\noindent\hskip6pt|\newcount\myindex|\par
+{\color{blue}\noindent\hskip6pt\llap\smex|\getcsvlistindex*[\myindex]{alpha}{one,two,three,four,five,alpha,beta}|}\par\vskip.5ex
+{\tt\string\the\string\myindex=\qquad\textbf{\the\myindex}}
+\par\hrulefill\par\vskip.5ex
+\ClearPage
+\subsubsection{\cmd{gettokslistindex} with \cmd{ifcase}}
+\hrulefill\par\vskip2ex\noindent
+\llap{\FE\,\smex}\par\vskip-2.5\baselineskip\strut
+\leavevmode\vadjust{Always purely expandable (no need of |\pdfstrcmp|, comparison done by |\ifx|):}
+\begin{Verbatim}
+ \ifcase \gettokslistindex{D}{LRDF\relax O}
+ What do to if L
+ \or What do to if R
+ \or What do to if D
+ \or What do to if F
+ \or What do to if \relax
+ \or What do to if O
+ \else Problem
+ \fi
+\end{Verbatim}
+{\tt Result=\qquad\bfseries
+\ifcase\gettokslistindex{D}{LRDF}
+ What do to if L
+\or What do to if R
+\or What do to if D
+\or What do to if F
+\else Problem
+\fi}\par
+\hrulefill\par\vskip.5ex
+\end{document}\endinput
+
+\endinput
+%%
+%% End of file `etextools-examples.tex'.
diff --git a/macros/latex/contrib/etextools/etextools.dtx b/macros/latex/contrib/etextools/etextools.dtx
new file mode 100644
index 0000000000..bea51ebc63
--- /dev/null
+++ b/macros/latex/contrib/etextools/etextools.dtx
@@ -0,0 +1,5429 @@
+% \iffalse meta-comment
+% etextools : e-TeX tools for LaTeX Users and package Writers (v.3.1415926 - 2010/12/07)
+%
+% This work may be distributed and/or modified under the
+% conditions of the LaTeX Project Public License, either
+% version 1.3 of this license or (at your option) any later
+% version. The latest version of this license is in
+% http://www.latex-project.org/lppl.txt
+%
+% This work consists of the main source file etextools.dtx
+% and the derived files
+% etextools.sty, etextools.ins, etextools.drv
+% etextools-examples.tex
+% etextools.pdf and etextools-examples.pdf
+%
+% Unpacking:
+% (a) If etextools.ins is present:
+% etex etextools.ins
+% (b) Without etextools.ins:
+% etex etextools.dtx
+% (c) If you insist on using LaTeX
+% latex \let\install=y\input{etextools.dtx}
+% (quote the arguments according to the demands of your shell)
+%
+% Documentation:
+% (pdf)latex etextools.dtx
+% (pdf)latex etextools-examples.tex
+%<*ignore>
+\begingroup
+ \def\x{LaTeX2e}%
+\expandafter\endgroup
+\ifcase 0\ifx\install y1\fi\expandafter
+ \ifx\csname processbatchFile\endcsname\relax\else1\fi
+ \ifx\fmtname\x\else 1\fi\relax
+\else\csname fi\endcsname
+%</ignore>
+%<*install>
+\input docstrip.tex
+\Msg{************************************************************************}
+\Msg{* Installation *}
+\Msg{* Package: etextools 2010/12/07 v.3.1415926 e-TeX tools for LaTeX Users and package Writers *}
+\Msg{************************************************************************}
+
+\keepsilent
+\askforoverwritefalse
+
+\let\MetaPrefix\relax
+\preamble
+
+This is a generated file.
+
+This work may be distributed and/or modified under the
+conditions of the LaTeX Project Public License, either
+version 1.3 of this license or (at your option) any later
+version. The latest version of this license is in
+ http://www.latex-project.org/lppl.txt
+
+This work consists of the main source file etextools.dtx
+and the derived files
+ etextools.sty, etextools.pdf, etextools.ins,
+and etextools-examples.tex
+
+\endpreamble
+\let\MetaPrefix\DoubleperCent
+
+\generate{%
+ \file{etextools.ins}{\from{etextools.dtx}{install}}%
+ \file{etextools.sty}{\from{etextools.dtx}{package}}%
+}
+\askforoverwritefalse
+\generate{%
+ \file{etextools.drv}{\from{etextools.dtx}{driver}}%
+ \file{etextools-examples.tex}{\from{etextools.dtx}{example}}%
+}
+
+\obeyspaces
+\Msg{************************************************************************}
+\Msg{*}
+\Msg{* To finish the installation you have to move the following *}
+\Msg{* file into a directory searched by TeX: *}
+\Msg{*}
+\Msg{* etextools.sty *}
+\Msg{*}
+\Msg{* To produce the documentation run the file `etextools.dtx' *}
+\Msg{* through LaTeX. *}
+\Msg{*}
+\Msg{* Happy TeXing! *}
+\Msg{*}
+\Msg{************************************************************************}
+
+\endbatchfile
+%</install>
+%<*ignore>
+\fi
+%</ignore>
+%<*driver>
+\edef\thisfile{\jobname}
+\def\thisinfo{The \thispackage\ package -- an \eTeX{} package for \LaTeX{}}
+\def\thisrevision{3.1415926}
+\def\thisdate{20 December 2010}
+\PassOptionsToPackage{hyperindex=false,pdfusetitle,colorlinks,pdfpagelabels,pdfencoding=auto}{hyperref}
+\PassOptionsToPackage{svgnames}{xcolor}
+%-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+\documentclass[a4paper,oneside]{ltxdockit}
+\usepackage[latin1]{inputenc}
+\usepackage[american]{babel}
+\usepackage{bbding}
+\usepackage{doc,tocloft,stmaryrd,amsmath,amssymb,xspace,graphicx,geometry}
+\usepackage{fancyhdr,titlesec,relsize,framed,enumitem,embedfile,xcolor}
+\let\Cross\relax
+\usepackage{interfaces}
+\usepackage{etoolbox,marvosym,wasysym,soul,makecell,colortbl,arydshln,numprint,bookmark}
+\CodelineNumbered\CodelineIndex
+\usepackage[expansion=all,protrusion=none]{microtype}
+\usepackage{tabu}[2010/12/07]\tracingtabu
+\csname endofdump\endcsname
+\usepackage{fancyvrb}
+\usepackage{umrand}
+\newrobustcmd*\cmdLabel[1]{\csgdef{cmdlabel->#1}{}}
+\embedfile{\thisfile.dtx}
+\geometry{left=4.5cm,marginparwidth=14pt,right=1.1cm,top=3mm,headsep=3mm,bottom=3mm,footskip=8mm,includeheadfoot}
+\csdef{ltd@email}#1{\href{mailto:#1}{\footnotesize\mdseries#1}}
+\titlepage{%
+ title={The \thispackage\footnotemark macros},
+ subtitle={An \etex package providing useful (purely expandable) tools \\ for LaTeX Users and package Writers},
+ url={http://www.ctan.org/tex-archive/macros/latex/contrib/etextools/},
+ author={\FC},
+ email={florent.chervet@free.fr},
+ revision={\footnotesize\thisrevision},
+ date={\footnotesize\thisdate}}
+\hypersetup{%
+ pdftitle={The etextools package},
+ pdfsubject={An e-TeX package providing useful tools for LaTeX package writers -- essay on purely expandability},
+ pdfauthor={Florent CHERVET},
+ colorlinks,linkcolor=reflink,urlcolor=spot,
+ pdfkeywords={tex, e-tex, latex, package, programming},
+ bookmarksopen=true,bookmarksopenlevel=2}
+\begin{document}
+ \DocInput{\thisfile.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \CheckSum{3781}
+%
+% \CharacterTable
+% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+% Digits \0\1\2\3\4\5\6\7\8\9
+% Exclamation \! Double quote \" Hash (number) \#
+% Dollar \$ Percent \% Ampersand \&
+% Acute accent \' Left paren \( Right paren \)
+% Asterisk \* Plus \+ Comma \,
+% Minus \- Point \. Solidus \/
+% Colon \: Semicolon \; Less than \<
+% Equals \= Greater than \> Question mark \?
+% Commercial at \@ Left bracket \[ Backslash \\
+% Right bracket \] Circumflex \^ Underscore \_
+% Grave accent \` Left brace \{ Vertical bar \|
+% Right brace \} Tilde \~}
+%
+% \DoNotIndex{\begin,\CodelineIndex,\CodelineNumbered,\def,\DisableCrossrefs,\if,\scalebox,\TeX,\strut,\q,\quad\,\qquad,\Next}
+% \DoNotIndex{\DocInput,\EnableCrossrefs,\end,\GetFileInfo,\PackageWarning,\PackageError\ParaFilt,\parskip,\parsep,\ProcessOptions,\documentclass}
+% \DoNotIndex{\NeedsTeXFormat,\OnlyDescription,\RecordChanges,\usepackage,\protected,\reserved@a,\reserved@b,\reserved@c,\reserved@d}
+% \DoNotIndex{\ProvidesClass,\ProvidesPackage,\ProvidesFile,\RequirePackage,\RESULT}
+% \DoNotIndex{\filename,\fileversion,\filedate,\let}
+% \DoNotIndex{\@listctr,\@nameuse,\csname,\else,\endcsname,\expandafter}
+% \DoNotIndex{\gdef,\global,\if,\item,\newcommand,\nobibliography}
+% \DoNotIndex{\par,\providecommand,\relax,\renewcommand,\renewenvironment}
+% \DoNotIndex{\stepcounter,\usecounter,\nocite,\fi}
+% \DoNotIndex{\@fileswfalse,\@gobble,\@ifstar,\@unexpandable@protect}
+% \DoNotIndex{\AtBeginDocument,\AtEndDocument,\begingroup,\endgroup}
+% \DoNotIndex{\frenchspacing,\MessageBreak,\newif,\PackageWarningNoLine}
+% \DoNotIndex{\protect,\string,\xdef,\ifx,\texttt,\@biblabel,\bibitem}
+% \DoNotIndex{\z@,\wd,\wheremsg,\vrule,\voidb@x,\verb,\bibitem}
+% \DoNotIndex{\FrameCommand,\MakeFramed,\FrameRestore,\hskip,\hfil,\hfill,\hsize,\hspace,\hss,\hbox,\hb@xt@,\endMakeFramed,\escapechar}
+% \DoNotIndex{\do,\date,\if@tempswa,\@tempdima,\@tempboxa,\@tempswatrue,\@tempswafalse,\ifdefined,\ifhmode,\ifmmode,\cr}
+% \DoNotIndex{\box,\author,\advance,\multiply,\Command,\outer,\next,\leavevmode,\kern,\title,\toks@,\trcg@where,\tt}
+% \DoNotIndex{\the,\width,\star,\space,\section,\subsection,\textasteriskcentered,\textwidth}
+% \DoNotIndex{\",\:,\@empty,\@for,\@gtempa,\@latex@error,\@namedef,\@nameuse,\@tempa,\@testopt,\@width,\\,\m@ne,\makeatletter,\makeatother}
+% \DoNotIndex{\maketitle,\parindent,\setbox,\x,\kernel@ifnextchar}
+% \DoNotIndex{\un,\deux,\xx,\tt,\title,\times,\texttt,\tableofcontents,\&,\@preline,\@redef,\\,\`,\|,\ ,\author}
+% \DoNotIndex{\bfseries,\clearpage,\cmd,\csvloopTest,\defineparser,\endinput,\expandnextTest}
+% \DoNotIndex{\fancyhf,\fancyhead,\FE@testoptTest,\FE@ifstarTest,\get@params,\goodbreak,\hypersetup,\iffirstcharTest,\ifsinglecharTest}
+% \DoNotIndex{\llap,\rlap,\longrightarrow,\make@macro,\makequotes,\MakeShortVerb,\mdseries,\multicolumn,\mylist,\textsl,\textsc,\uparrow,\myindex,\mkern}
+% \DoNotIndex{\nobreak,\noindent,\null,\OPTmacro,\notstarred,\pagestyle,\preline,\quad,\result,\smex,\starmacro,\starred,\strip@macro,\@nil,\@ne}
+% \DoNotIndex{\strip@macroprefix,\strip@prefix,\sty,\subsubsection,\subtitle,\test}
+% \DoNotIndex{\testcsvloop,\testexpandnext,\testFE@testopt,\testFE@ifstar,\testgetlistitem,\testiffirstchar,\testifsinglechar,\getlistitemTest}
+% \DoNotIndex{\testgetlistindex,\testxgetlistindex}
+% \DoNotIndex{\textbf,\textcolor,\vskip,\long,\hrulefill,\&,\@get@params,\geometry,\edef,\BySeven,\optmacro,\@xifblank,\ettl@onlyonce,\ettl@undefined,\usercmd,\noexpand}
+% \DoNotIndex{\@listedel,\@listgdel,\@listxdel,\bindnasrepma,\color,\copy,\count,\definecolor,\finale,\testi,\small,\newcount}
+% \DoNotIndex{\lastcmditem,\laststarredcmditem,\textsf,\textvb,\textvbbf,\or,\thispackage,\TMP@EnsureCode,\topsep,\usefont,\upshape}
+% \DoNotIndex{\vadjust,\nnn,\newrobustcmd,\macroA,\macroB,\m@th,\itemsep,\ifpdfTeX,\iftrue,\FE,\fe,\FE@ifcharequal,\hyperdef,\iffalse}
+% \DoNotIndex{\cslet,\csedef,\csgdef,\blue,\baselineskip,\active,\afterassignment,\apptocmd,\dg,\dgbf,\DefineShortVerb,\DefineVerbatimEnvironment}
+% \DoNotIndex{\#,\&,\,\@list@extra,\[,\],\ ,\AtEndOfPackage,\arabic,\ClearPage,\csdef,\csundef,\ifnumcomp,\ifundef,\ifcsdef,\ifcsmacro}
+% \DoNotIndex{\ifcsundef,\ifdef,\ifcsparam,\pdfFE,\textvb,\unless,\unexpanded,\undef,\letcs}
+%
+% \makeatletter
+% \let\@begintochook \relax \let\@endtochook \relax
+% \newrobustcmd*\Xspace{\ifnum\catcode`\ =10\relax\expandafter\xspace\fi}
+% \newrobustcmd*\FC{{\color{copper}\usefont{T1}{fts}xn FC}}
+% \newrobustcmd\ClearPage{\@ifstar{\clearpage}{}}
+% \newrobustcmd\thispackage{\xpackage{\spot\thisfile}\Xspace}
+% \newrobustcmd\Thispackage{\Xpackage[\thisfile]{\spot\thisfile}\Xspace}
+% \newrobustcmd\xpackage[1]{{\usefont{T1}{lmss}{bx}{n}\db\mbox{#1}}}
+% \newcommand\Xpackage{\@dblarg\X@package}
+% \protected\def\X@package[#1]#2{\xpackage {#2\footnotemark}\footnotetext {\noindent \xpackage{#2}: \CTAN{macros/latex/contrib/#1}}}
+% \newrobustcmd*\CTAN[1]{\href{http://www.ctan.org/tex-archive/#1}{\nolinkurl{CTAN:#1}}}
+% \font\ding=dingbat scaled 800
+% \font\manual=manfnt
+% \font\umranda=umranda \font\umrandasmall=umranda scaled800
+% \robustify\footnotesize \robustify\mdseries
+% \catcode`\§\active\def§{\par\nobreak\vspace*{-\parskip}\nobreak}
+% \catcode`\¤\active\let¤\quad
+% \newcommand\smex{\leavevmode\hb@xt@2em{\hfil\spot$\longrightarrow$\hfil}}
+% \newcommand*\manfntsymb[1]{\manual\symbol{#1}}
+% \newcommand\dbend{\marginpar{\rmkcolor\manfntsymb{127}}\Xspace} \newcommand\manerrarrow{\manfntsymb{121}}
+% \newcommand*\tinybullet[1][3pt]{\kern.4em\raise2pt\hbox{\fontsize{#1}\z@\selectfont\textbullet}\kern.4em}
+% \renewcommand\#[1]{{\usefont{T1}{pcr}{bx}{n}\char`\##1}}
+% \renewcommand\%{{\vb\char`\%}}
+% \DeclareInputText{128}{\texteuro}
+% \let\eTeX@mathsubscript=_
+% \catcode`\_ 13 \def _{\@ifnextchar _\DoubleSubScript\eTeX@mathsubscript}
+% \long\def\DoubleSubScript_#1{\eTeX@mathsubscript{\eTeX@mathsubscript{#1}}}
+% \newcommand\negquad{\hskip-1em\relax} \newcommand\negqquad{\hskip-2em\relax}
+% \renewcommand\ttdefault{txtt}
+% \renewcommand\rmdefault{ua1}
+% \renewcommand\sfdefault{txss}
+% \newrobustcmd\verbfont{\usefont{T1}{\ttdefault}{\f@series}{n}} \let\vb\verbfont
+% \newrobustcmd\verbfontbf{\usefont{T1}{\ttdefault}{b}{n}} \let\vbbf\verbfontbf
+% \newrobustcmd\verbfontmd{\usefont{T1}{\ttdefault}{m}{n}} \let\vbmd\verbfontmd
+% \newrobustcmd\textvb[2][]{\mbox{\vb#1#2}} \newrobustcmd\textvbbf[2][]{\mbox{\vbbf#1#2}} \let\textbfvb\textvbbf
+% \renewcommand\tt{\usefont{T1}{pcr}{\f@series}{n}\upshape} \newcommand\ttbf{\usefont{T1}{pcr}{b}{n}}
+% \newrobustcmd\CS[2][]{\mbox{\tt#1\expandafter\@gobble\string\\#2}}
+% \newrobustcmd\CSbf[2][]{\mbox{\ttbf#1\expandafter\@gobble\string\\#2}}
+% \renewrobustcmd\cs[2][]{\mbox{\vb#1\expandafter\@gobble\string\\#2}}
+% \newrobustcmd\csbf[2][]{\mbox{\vbbf#1\expandafter\@gobble\string\\#2}}
+% \renewrobustcmd\itshape{\not@math@alphabet\itshape\mathit\normalfont\fontshape\itdefault\selectfont}
+% \newrobustcmd\nnn{\normalfont\upshape\mdseries}
+% \newrobustcmd\nitbf{\normalfont\itshape\bfseries}
+% \newrobustcmd\nslbf{\normalfont\slshape\bfseries}
+% \newrobustcmd\nit{\normalfont\itshape}\newrobustcmd\nsl{\normalfont\slshape}
+% \newrobustcmd\nbf{\normalfont\bfseries}\newrobustcmd\nup{\normalfont\upshape}
+% \newrobustcmd\itbf{\itshape\bfseries}
+% \newrobustcmd\sfbf{\sffamily\bfseries}
+% \newrobustcmd\textsfbf[1]{{\sffamily\bfseries #1}} \let\textbfsf\textsfbf \let\textbf\textsfbf
+% \newrobustcmd\textttbf[1]{{\ttfamily\bfseries #1}} \let\textbftt\textttbf
+% \newrobustcmd\textitbf[1]{{\itshape\bfseries #1}} \let\textbfit\textitbf
+% \newrobustcmd\textslbf[1]{{\slshape\bfseries #1}} \let\textbfsl\textslbf
+% \newrobustcmd\textsfsl[1]{{\slshape\sffamily #1}} \let\textslsf\textsfsl \let\emph\textsfsl
+% \newrobustcmd\textbfbf[1]{{\rmfamily\bfseries #1}}
+% \newrobustcmd\txtbf[2][]{\textbf{#1#2}}
+% \newrobustcmd\hlbf[1]{\bfseries\hl{#1}}
+% \newrobustcmd\scs[1]{\expandafter\@gobble\string\\#1}
+% \newrobustcmd\md{\mdseries}\newrobustcmd*\mdsm{\mdseries\small}\newrobustcmd*\mdfs{\mdseries\footnotesize}
+% \newrobustcmd\prmb[1]{\prm{\bfseries #1}} \newrobustcmd\PRM[2][]{\prm{#1#2}}
+% \newrobustcmd\CH[2][]{`\,\textvb[#1]{#2}\,`\Xspace}
+% \newrobustcmd\chcat[3][\blue]{\textvb[#1]{#2}$__{\mathbf{#3}}$}
+% \newrobustcmd\stform[2][\red]{{\ttbf#1\if*#2\textasteriskcentered\else#2\fi}}%
+% \newrobustcmd\spview[1][\blue]{{\ttbf#1\textvisiblespace}}
+% \newrobustcmd\tsptb{\medspace\textbackslash}
+% \renewrobustcmd\{{\ifmmode\lbrace\else{\usefont{T1}{cmr}{\f@series}{n}\textbraceleft}\fi}
+% \renewrobustcmd\}{\ifmmode\rbrace\else{\usefont{T1}{cmr}{\f@series}{n}\textbraceright}\fi}
+% \newrobustcmd*\thisyear{2010}
+% \renewrobustcmd\ltxsyntaxlabelfont{\spot\usefont{T1}{pcr}{b}{n}}
+% \newrobustcmd\mycolorbox[1][{[rgb]{1.00,1.00,0.79}}]{\@testopt{\my@colorbox[{#1}]}{\red}}
+% \def\M{\@ifstar{\M@i\@firstofone}{\M@i\meta}}
+% \def\M@i#1{\@ifnextchar[^^A]
+% {\M@square#1}
+% {\@ifnextchar(^^A)
+% {\M@paren#1}
+% {\M@brace#1}}^^A
+% }
+% \def\M@square#1[#2]{\M@Bracket[{#1{#2}}]}
+% \def\M@paren#1(#2){\M@Bracket({#1{#2}})}
+% \def\M@brace#1#2{\M@Bracket\{{#1{#2}}\}}
+% \def\M@Bracket#1#2#3{{\ttfamily#1#2#3}}
+% \protected\long\def\my@colorbox[#1][#2]#3{\colorbox#1{#2#3}}
+% \def\Underbrace#1_#2{$\underbrace{\vtop to2ex{}\hbox{#1}}_{\hbox{\footnotesize#2}}$}
+% \newrobustcmd*\mydotleader[2][\z@]{\leavevmode\xleaders\hbox to\dimexpr1.7pt+#1{\hss\raise#2\hbox{$\scriptscriptstyle\cdotp$}\hss}}
+% \globcount\ettl@AfterGroup
+% \newrobustcmd\AfterGroup[1]{\global\advance\ettl@AfterGroup1\relax
+% \csxdef{ettl@aftergroup@hook\the\ettl@AfterGroup}{\expandonce{#1}}%
+% \expandafter\aftergroup\csname ettl@aftergroup@hook\the\ettl@AfterGroup\endcsname}
+% \long\def\avoidcsvoid[#1]#2{\expandafter\ifcsvoid\expandafter{\romannumeral-`\q#2}{#1}{#2}} \let\avoidvoidcs\avoidcsvoid
+% \long\def\avoidvoid[#1]#2{\ifdefvoid{#2}{#1}{#2}}
+% \newrobustcmd*\movepage[2][]{\advance\hsize by#2\hoffset\ifblank{#1}{-#2}{#1}\linewidth\the\hsize\textwidth\the\hsize}
+% \newrobustcmd\pagenumberdisplay{\leavevmode\lower5pt\hbox{\ttfamily\oldstylenums{\thepage} / \oldstylenums{\pageref{LastPage}}}}
+% \footskip=0pt
+% \pagesetup[corpus]{
+% head/rule/width=0pt,
+% head/left=\@tempdima\dimexpr\hsize+\thesecwidth\relax\rmkcolor
+% \hskip-\thesecwidth\rlap{\lower6pt\hbox to\@tempdima{\mydotleader\z@\hfill}}\hfill
+% \small The \textcolor{black}\thispackage\ macros -- and \eTeX{} package for \LaTeX\hfill,
+% foot/left/font=\color[gray]{.35}\footnotesize,
+% foot/left=\vbox to\z@{\vss\rotatebox{90}{\thispackage\unskip\enspace\copyright\,\thisyear\enspace\scriptsize\lower.3ex\hbox{\NibRight}\enspace\FC}},
+% foot/left/offset=4cm,
+% foot/right/offset=.5cm,
+% foot/right=\pagenumberdisplay,
+% }
+% \pagesetup[toc]{
+% head/rule/width=0pt,
+% foot/right=\pagenumberdisplay,
+% }
+% \pagesetup[empty]{norules,
+% foot/left/font=\footnotesize,
+% foot/left=\vbox to\z@{\vss\rotatebox{90}{\thispackage\unskip\enspace\copyright\,\thisyear\enspace\scriptsize\lower.3ex\hbox{\NibRight}\enspace\FC}},
+% foot/left/offset=2cm,
+% }
+% ^^A COLORS :
+% \let\Org@definecolor\definecolor
+% \renewrobustcmd\definecolor[1][]{\ettl@definecolor{#1}}
+% \newrobustcmd\ettl@definecolor[4]{\Org@definecolor{#2}{#3}{#4}%
+% \ifblank{#1}{\ifcsname#2\endcsname\expandafter\expandafter\expandafter\renewrobustcmd
+% \else\expandafter\expandafter\expandafter\newrobustcmd
+% \fi\csname#2\endcsname{\color{#2}}}
+% {\newrobustcmd#1{\color{#2}}}}
+% \definecolor{spot}{rgb}{1.00,0.33,0.00} \definecolor{fecc}{rgb}{.2,.6,.2}
+% \definecolor[\macrocodecolor]{macrocode}{rgb}{0.18,0.00,0.45}
+% \definecolor{ly}{rgb}{0.81,1.00,0.42}
+% \definecolor{dc}{rgb}{0,0.6,0.6}
+% \definecolor{cream}{rgb}{1.00,1.00,0.77} \definecolor{db}{rgb}{0.00,0.00,0.25}
+% \newrobustcmd\black{\color{black}} \newrobustcmd\blue{\color{blue}}
+% \renewcommand*\MacroFont{\usefont{T1}{lmtt}{m}{n}\macrocodecolor}
+% \pretocmd\macrocode{\def§{\IeC{\S}}\let¤\textcurrency}{}{}
+% \apptocmd\macro@font{\macrocodecolor\let\AltMacroFont\macro@font}{}{}
+% \definecolor{reflink}{rgb}{1.00,0.00,0.00} \definecolor{reflinkabstract}{rgb}{0.79,0.00,0.00}
+% \definecolor{rmklink}{rgb}{.2,.2,.2}
+% \def\reflink{\ifx\current@color\default@color \rmklink\else\let\current@color\reflink@color\set@color\fi}\let\reflink@color\current@color
+% \definecolor[\rmkcolor]{rmk}{gray}{.35} \definecolor{copper}{rgb}{0.71,0.45,0.02}
+% \definecolor{dg}{rgb}{0.16,0.33,0.00} \definecolor{ddg}{rgb}{0.11,0.21,0.00}
+% \definecolor{shadecolor}{rgb}{0.93,0.94,0.81}^^A for framed
+% \definecolor{dgray}{gray}{.3} \definecolor[\rred]{r}{rgb}{1,0,0}
+% \definecolor{dr}{rgb}{0.49,0.00,0.00} \let\red\dr
+% \newrobustcmd\rmk{\footnotesize\rmkcolor\@ifstar{}{\endgraf\nobreak}}
+% \newrobustcmd\hint{\rmk\everypar{\marginpar{\footnotesize\textcolor{rmk}{hint}$\bigstar$}\everypar{}}}
+% ^^A\setul{2pt}{1pt}
+% \newrobustcmd\eol{\textcolor[gray]{.5}{$\hookleftarrow$}}
+% \newrobustcmd\mysep[1][\blue]{{\smaller[2]\PRM[#1]{sep}}}
+% \newrobustcmd\itemitemitem{\@ifstar\itemitemitem@star\itemitemitem@nost}
+% \newrobustcmd\itemitemitem@star[1][\mysep]{\textvb{item}#1\textvb{item}#1\textvb{item}}
+% \newrobustcmd\itemitemitem@nost[1][\mysep]{\{\textvb{item}#1\textvb{item}#1\textvb{item}\}}
+% \newenvironment{codecomment}{\par\vskip\parskip\begin{small}\color[gray]{.2}\parskip=0pt}{\end{small}}
+% \renewcommand\partformat{}\let\thepart\partformat\renewcommand\raggedpart{\hskip-\thesecwidth\centering}%
+% ^^A Labels:
+% \newrobustcmd*\cmdlabel[1]{\begingroup\let\stform\@empty
+% \protected@edef\cmdlabel@name{#1}\@onelevel@sanitize\cmdlabel@name
+% \xdef\cmdlabel@name{\cmdlabel@name}\endgroup
+% \cslet{\detokenize{cmdlabel->}\cmdlabel@name}\@empty
+% \immediate\write\@mainaux{\cmdLabel{\cmdlabel@name}}\hyperdef{cmdlabel}{\cmdlabel@name}{}}
+% \newrobustcmd*\cmdref{\let\reflink@color\current@color
+% \@ifstar{\@dblarg\cmdrefst}{\@ifchar={\@dblarg\cmdrefeq}{\@dblarg\@cmdref}}}
+% \def\cmdrefst[#1]#2{\@cmdref[impl:#1]{#2}}
+% \def\cmdrefeq[#1]#2{\def\cmdref@display##1{\underline{\mbox{\reflink\vb ##1}}}\cmd@hyper[#1]{#2}}
+% \newcommand\cmdrefdisplay[1]{\underline{\mbox{\reflink\vb\textbackslash #1}}}
+% \def\@cmdref[#1]#2{\let\cmdref@display\cmdrefdisplay \cmd@hyper[#1]{#2}}
+% \protected\def\cmd@hyper[#1]{\@testopt{\cmd@@hyper[{#1}]}{}}
+% \def\cmd@@hyper[#1][#2]#3{\@testopt{\cmd@@@hyper[{#1}][{#2}]{#3}}{\Xspace}}
+% \def\cmd@@@hyper[#1][#2]#3[#4]{\ifcsdef{\detokenize{cmdlabel->#1}}%
+% {#2\hyperref{}{cmdlabel}{\detokenize{#1}}{\cmdref@display{#3}}#4}%
+% {#2\cmdref@display{\colorbox{black}{\color{white}#3}}#4}}%
+% \newrobustcmd*\seeimpl[2][]{\expandafter\@seeimpl\expandafter{\romannumeral-`\q#2}[{#1}]}
+% \long\def\@seeimpl#1[#2]{\ifblank{#1}{}
+% ^^A{\vadjust\bgroup\vtop to-3pt\bgroup\vss\hbox to\z@\bgroup\hss
+% ^^A \colorbox{yellow}{\textcolor{red}{\large\Laserbeam}}\kern\dimexpr5.3em#2\egroup\egroup\egroup\unskip\ignorespaces}
+% {\def\cmdref@display##1{\colorbox{yellow}{\textcolor{red}{\large##1}}}%
+% \cmd@@@hyper[impl:#1][\vadjust\bgroup\vtop to-3pt\bgroup\vss\hbox to\z@\bgroup\hss]{\Laserbeam}[\kern\dimexpr5.3em#2\egroup\egroup\egroup\unskip\ignorespaces]}}
+% \newsavebox\seedescbox\setbox\seedescbox\hbox to\z@{\kern.4em\colorbox{green}{\textcolor{red}{\SunshineOpenCircled}}\hss}
+% \newrobustcmd*\seedesc[1]{\ifblank{#1}{\copy\seedescbox}
+% \ifcsdef{cmdlabel->#1}{%
+% \vadjust{\vskip-1.5\ht\seedescbox\hfill
+% \hbox to\z@{\kern.4em\hyperref{}{cmdlabel}{\detokenize{#1}}{\colorbox{green}{\textcolor{red}{\SunshineOpenCircled}}}\hss}}}
+% {\vadjust{\vskip-1.5\ht\seedescbox\hfill
+% \hbox to\z@{\kern.4em\colorbox{black}{\textcolor{white}{\SunshineOpenCircled}}\hss}}}}
+% \newsavebox\FE@box \setbox\FE@box\hbox{$\m@th\bindnasrepma$}
+% \setbox\FE@box\hbox{\scalebox{2}{$\copy\FE@box\mkern-13.5mu\copy\FE@box\mkern-13.5mu\copy\FE@box$}}
+% \newsavebox\FEI@box \setbox \FEI@box\hbox{\rlap{\bfseries\color{red}\raisebox{-3pt}{\LARGE\bfseries\oldstylenums{1}}}\kern1pt{\fecc\unhcopy\FE@box}}
+% \newsavebox\FEII@box \setbox\FEII@box\hbox{\rlap{\bfseries\color{red}\raisebox{-3pt}{\LARGE\bfseries\oldstylenums{2}}}\kern1pt{\fecc\unhcopy\FE@box}}
+% \newsavebox\pdfFE@box \setbox\pdfFE@box\hbox{\llap{\hbox to3.3em{\dg\bfseries\textsf{pdf}\TeX{}}}\copy\FE@box}
+% \newsavebox\FEtiny@box\setbox\FEtiny@box\hbox{\scalebox{.6}{$\copy\FE@box\mkern-33mu\copy\FE@box$}}
+% \newcommand*\FEbox[1]{\raisebox{\glueexpr#1}{\fecc\copy\FE@box}}
+% \newrobustcmd\FEtiny[1][.2ex]{\raise\glueexpr#1\hbox to\z@{\hss\fecc\copy\FEtiny@box\kern.35em}}
+% \newcommand*\pdfFEbox[1]{\raisebox{\glueexpr#1}{\fecc\copy\pdfFE@box}}
+% \newcommand*\FEIbox[1]{\raisebox{\glueexpr#1}{\copy\FEI@box}}
+% \newcommand*\FEIIbox[1]{\raisebox{\glueexpr#1}{\copy\FEII@box}}
+% \newcommand\AddtoFE[1]{\listxadd#1\lastcmditem\listxadd#1\laststarredcmditem}
+% \newcommand\FE{\@ifstar{\AddtoFE\FEcmdlist}
+% {\ifx\@currenvir\macroenvirname \marginpar{\FEbox{-\the\baselineskip*2-4pt}}
+% \else \marginpar{\FEbox{-2pt}} \AddtoFE\FEcmdlist\seeimpl@display
+% \fi}}
+% \newcommand\pdfFE{\@ifstar{\AddtoFE\pdfFEcmdlist}
+% {\ifx\macroenvirname\@currenvir \marginpar{\pdfFEbox{-\the\baselineskip*2-4pt}}
+% \else \marginpar{\pdfFEbox{-2pt}} \AddtoFE\pdfFEcmdlist\seeimpl@display[+1.5em]
+% \fi}}
+% \newcommand\FEI{\@ifstar{\AddtoFE\FEIcmdlist\AddtoFE\FEcmdlist}
+% {\ifx\macroenvirname\@currenvir \marginpar{\FEIbox{-\the\baselineskip*2-4pt}}
+% \else \marginpar{\FEIbox{-2pt}} \AddtoFE\FEIcmdlist\AddtoFE\FEcmdlist\seeimpl@display
+% \fi}}
+% \newcommand\FEII{\@ifstar{\AddtoFE\FEIIcmdlist\AddtoFE\FEcmdlist}
+% {\ifx\macroenvirname\@currenvir \marginpar{\FEIIbox{-\the\baselineskip*2-4pt}}
+% \else \marginpar{\FEIIbox{-2pt}} \AddtoFE\FEIIcmdlist\AddtoFE\FEcmdlist\seeimpl@display
+% \fi}}
+% \newcommand\notFE{\@ifstar\relax\seeimpl@display}
+% \def\macroenvirname{macro}\let\lastcmditem\@empty \let\laststarredcmditem\@empty
+% ^^A Patching of \cmditem to make automatic cross reference with \FE symbol:
+% \let\Org@ltd@cmditem\ltd@cmditem
+% \let\Org@ltd@pdfbookmark\ltd@pdfbookmark
+% \renewcommand\ltd@pdfbookmark[2]{\begingroup\let\stform\@empty
+% \protected@edef\ltd@pdfbookmark{\endgroup\noexpand\Org@ltd@pdfbookmark{#1}{#2}}\ltd@pdfbookmark}
+% \def\@ifchar#1#2{\expandafter\@ifnextchar\string#1{\@firstoftwo{#2}}}
+% ^^A\let\cmditem\relax
+% ^^A \cmditem - => pas d'entrée dans la liste des commandes / laststarredcmditem et labelize
+% ^^A \cmditem * => idem mais entrée dans la liste des commandes
+% ^^A \cmditem => entrée dans la liste \cmditem + => idem mais couleur \spot dans la liste / lastcmditem et labelize
+% ^^A \cmditem @ => pas d'impression (juste l'entrée dans la liste, avec couleur normale)
+% ^^A \cmditem +[..]@ => pas d'impression (juste l'entrée dans la liste, avec couleur \spot)
+% \renewrobustcmd\ltd@cmditem[1][]{\goodbreak
+% \@ifchar-{\my@cmditem@starred{#1}\@gobble}%^^A \cmditem- => pas d'entrée dans la liste des fonctions
+% {\@ifstar{\my@cmditem@starred{#1}\@firstofone}{\my@cmditem{#1}}}}%^^A \cmditem* => entrée dans la liste des fonctions
+% \newrobustcmd*\my@cmditem@starred[3]{%^^A starred = \cmditem- ou \cmditem*
+% \edef\laststarredcmditem{\ifblank{#1}{#3}{#1}}%^^A
+% \edef\cmditem@end@hook{\cmditem@labelize{\ifblank{#1}{#3}{#1}}}%^^A
+% #2{\expandafter\addcommand\expandafter{\laststarredcmditem}{}{#3}}%^^A
+% \Org@ltd@cmditem{#3}}^^A Make bookmark anyway (no star form)
+% \newrobustcmd*\my@cmditem[1]{\@ifchar+%^^A \cmditem+ => couleur \spot dans la liste des commandes
+% {\bookmarksetup{color*=spot}^^A
+% \@ifchar @{\my@cmd@item{#1}\spot\@gobble}{\my@cmd@item{#1}\spot\@firstofone}}%^^A \cmditem+@ => couleur \spot (dans la liste) mais pas d'impression dans le texte
+% {\@ifchar @{\my@cmd@item{#1}{}\@gobble}{\my@cmd@item{#1}{}\@firstofone}}}
+% \newrobustcmd*\my@cmd@item[4]{%
+% \let\lastcmditem\@empty\let\laststarredcmditem\@empty
+% \edef\lastcmditem{\ifblank{#1}{#4}{#1}}%
+% \def\cmditem@end@hook{\cmditem@labelize{\avoidvoid[\laststarredcmditem]\lastcmditem}}
+% \expandafter\addcommand\expandafter{\lastcmditem}{#2}{#4}%
+% #3{\Org@ltd@cmditem{#4}}}
+% \newrobustcmd\addcommand[3]{%
+% \refstepcounter{command}%
+% \addcontentsline{cmds}{command}{\protect\numberline{\cftcommandnum{#1}{#2\arabic{command}}}\cftcommandfont#2{\protect\textbackslash#3}}}
+% \newrobustcmd\cftcommandnum[2]{\ifinlist{#1}\listofFEcommands \FEtiny{}\cftcommandfont \mdseries\sffamily\scriptsize\hfill #2\kern.4em}
+% \AtEndDocument{\immediate\write\@mainaux{%
+% \begingroup\catcode124 3\relax\gdef\noexpand\listofFEcommands{\detokenize\expandafter{\FEcmdlist}}\endgroup}}
+% \unless\ifdefined\listofFEcommands\let\listofFEcommands\@empty\fi
+% \newrobustcmd\seeimpl@display[1][]{\seeimpl[{#1}]{\avoidvoid[\laststarredcmditem]\lastcmditem}}%
+% \newrobustcmd*\cmditem@labelize[1]{\cmdlabel{#1}\hfill\par}
+% ^^A At the end of the ltxdockit scanner for \cmditem, the labelize-macro must be expanded:
+% \apptocmd\ltd@parseargs@end{\cmditem@end@hook}{}{}
+% ^^A Now Macro envir may use the labels:
+% \def\@Macro#1{\begin{macro}{#1}}
+% \newenvironment{Macro}[2][]{%
+% \expandafter\@Macro\expandafter{\@backslashchar#2} \cmdlabel{impl:#2}%
+% \ifblank{#1}{\Check@FEList{#2}\cmdlabel{impl:#2}}%
+% {\Check@FEList{#1}\cmdlabel{impl:#1}}}
+% {\end{macro}}
+% \def\Check@FEList#1{%
+% \ifinlist{#1}\FEIcmdlist \FEI
+% {\ifinlist{#1}\FEIIcmdlist \FEII
+% {\ifinlist{#1}\FEcmdlist \FE
+% {\ifinlist{#1}\pdfFEcmdlist \pdfFE{}}}}
+% \everypar\expandafter{\the\everypar\seedesc{#1}\everypar{}}}
+%
+% \newenvironment{Macro*}[2][]{%
+% \expandafter\@Macro\expandafter{\@backslashchar#2}%
+% \ifblank{#1}{\cmdlabel{impl:#2}}{\cmdlabel{impl:#1}}}
+% {\end{macro}}
+%
+% \DefineVerbatimEnvironment{VerbLines}{Verbatim}{gobble=1,frame=lines,framesep=6pt,fontfamily=txtt,fontseries=b}
+% \DefineVerbatimEnvironment{Verb}{Verbatim}{gobble=1}
+% \DefineVerbatimEnvironment{VerbZ}{Verbatim}{gobble=1}
+% \tocsetup{
+% part/skip=6pt,
+% subsection/number/width=1.5em,
+% subsection/number/before=\hbox to.5em\bgroup\hss,
+% subsection/number/after=\egroup\hbox to1em{\hss\tinybullet\hss},
+% subsection/pagenumbers/font=\scriptsize,
+% subsection/leader=\kern.4em\mydotleader[1pt]\z@\hfill,
+% subsection/skip=-.7pt,
+% section/skip=3pt,
+% section/number/width=1.5em,
+% section/font=\usekomafont{section}\large\bfseries\red,
+% part/font=\usekomafont{section}\large\bfseries,
+% section/number/before=\cftsecfont\hbox to.5em\bgroup\hss,
+% section/number/after=\egroup\raise.2ex\hbox to1em{\hss\scriptsize\Forward\hss},
+% }
+% \newlistof{command}{cmds}{}
+% \renewcommand\thecommand{\arabic{command}}
+% \def\Hy@currentbookmarklevel{\BKM@currentlevel}
+% \newlength\thesecwidth\thesecwidth=2.2cm
+%
+% \sectionformat\section[hang]{
+% font=\LARGE\bfseries,
+% label=\llap{\hbox to\thesecwidth{\hfil\arabic{section}\hfil\kern.4em{\spot\Forward}\kern.4em\hfil}},
+% labelsep=0pt,
+% left=0pt,
+% top=6pt plus4pt minus2pt,
+% bottom=3pt plus2pt minus1pt,
+% break=\penalty-3000,
+% bookmark={color=spot},
+% }
+% \newrobustcmd*\normalsubsecformat{\sectionformat\subsection[hang]{
+% font=\Large\bfseries,
+% label=\llap{\hbox to\thesecwidth{\arabic{section}\textbullet\arabic{subsection}\hfil{\fecc\manerrarrow}\hfil}},
+% labelsep=0pt,
+% left=0pt,
+% top=6pt plus4pt minus2pt,
+% bottom=3pt plus2pt minus1pt,
+% bookmark={color=ForestGreen,italic},
+% }
+% }
+% \newrobustcmd*\implementationsubsecformat{\sectionformat\subsection[hang]{
+% font=\Large\bfseries,
+% label=\llap{\hbox to\thesecwidth{I\textbullet\arabic{subsection}\hfil{\fecc\manerrarrow}\hfil}},
+% labelsep=0pt,
+% left=0pt,
+% top=6pt plus4pt minus2pt,
+% bottom=3pt plus2pt minus1pt,
+% }
+% \sectionformat\subsubsection[hang]{
+% font=\large\bfseries,
+% label=\llap{\hbox to\thesecwidth{I\textbullet\arabic{subsection}\textbullet\arabic{subsubsection}\hfil{\fecc--}\hfil}},
+% labelsep=0pt
+% }
+% }
+% \newrobustcmd*\firstsubsecformat{\sectionformat\subsection[hang]{
+% font=\large\bfseries,
+% label=\llap{\hbox to\thesecwidth{\hss\arabic{subsection}\hfil{\fecc\manerrarrow}\hfil}},
+% labelsep=0pt,
+% left=0pt,
+% top=5pt plus2pt minus2pt,
+% bottom=2pt plus1pt minus1pt,
+% break=\penalty-500,
+% }
+% \sectionformat\section{mark=}
+% }
+% \firstsubsecformat
+% \newcommand\Section{\@ifstar{\section*}{\@ifchar.{\@dblarg{\@Section.}}{\@dblarg{\@Section{}}}}}
+% \long\def\@Section#1[#2]#3{%
+% \ifblank{#1}{}{\let\WriteBookmarks\relax}%
+% \section[{\texorpdfstring{\protect\cftsecfont}{}#2}]{#3}}%
+% ^^A\ifblank{#1}{}{\let\WriteBookmarks\@empty\numdef\Hy@currentbookmarklevel{\Hy@currentbookmarklevel-1}}}
+% \newcommand\Subsection{\@ifstar{\subsection*}{\@ifchar.{\@dblarg{\@Subsection.}}{\@dblarg{\@Subsection{}}}}}
+% \long\def\@Subsection#1[#2]#3{%
+% \ifblank{#1}{}{\let\WriteBookmarks\relax}%
+% \subsection[{#2}]{#3}}%
+% ^^A\ifblank{#1}{}{\let\WriteBookmarks\@empty\numdef\Hy@currentbookmarklevel{\Hy@currentbookmarklevel-1}}}
+% \newsavebox\helpbox \newsavebox\helpboxx
+% \newcommand\hpbox{\copy\helpbox} \newcommand\hpboxx{\copy\helpboxx}
+% \lastlinefit999 \parindent\z@ \topsep\z@ \partopsep\z@ \parskip.3\baselineskip
+% \fontfamily{ua1}\selectfont \pagestyle{corpus}
+% \MakeShortVerb{\|}
+% \makeatother
+%
+% \begingroup \movepage{2cm}\vspace*{-1.2cm}\let\footnoterule\relax\skip\footins=-.3cm\footskip=0pt\enlargethispage\baselineskip
+% \definecolor{reflink}{gray}{0}\makeatletter
+% \newrobustcmd\corner[2][\spot\umranda]{\hbox{#1\rlap{\char'115}\char'#2}}
+% \setbox\helpbox\vbox to\z@{\lineskip-1.3pt\baselineskip\lineskip
+% \parshape 9 -1.5ex \z@ -3ex \z@ -4.3ex \z@ -5ex \z@ -5.6ex \z@ -5ex \z@ -4.3ex \z@ -3ex \z@ -1.5ex \z@\relax
+% \noindent\rlap{\Large\leftmoon\corner[\spot\umrandasmall]{17}}\strut\linebreak
+% \rlap{\Large\leftmoon}\strut\linebreak
+% \rlap{\Large\leftmoon}\strut\linebreak
+% \rlap{\Large\leftmoon}\strut\linebreak
+% \rlap{\Large\leftmoon}\strut\linebreak
+% \rlap{\Large\leftmoon}\strut\linebreak
+% \rlap{\Large\leftmoon}\strut\linebreak
+% \rlap{\Large\leftmoon}\strut\linebreak
+% \rlap{\Large\leftmoon\corner[\spot\umrandasmall]{21}}\vss}
+% \newsavebox\myb \setbox\myb\vtop to\z@{\hbox{\rlap{\lower1.9ex\hbox{\spot\umranda\char'111}}\lower17.2ex\hbox{\lower1.9ex\hbox{\spot\umranda\char'111}}}\vss}
+% \setbox\helpboxx\vbox{\hbox to\z@{\hbox to\hsize{\hfil\copy\helpbox\cleaders\copy\myb\hskip14cm\reflectbox{\copy\helpbox}\hfil}\hss}\printtitlepage}
+% \box\helpboxx \footnotetext {\noindent \thispackage: \CTAN{macros/latex/contrib/\thisfile}}
+%
+% \begingroup\makeatletter\parfillskip\z@
+% \tocsetup{
+% pagestyle=toc,
+% title=\mydotleader{.5ex}\hfill\kern.5em\Large\bfseries Contents\kern.5em\mydotleader{.5ex}\hfill\kern\z@,
+% title/bottom=-12pt,
+% title/top=12pt,
+% part/leader=\kern.4em\mydotleader{.4ex}\hfill\hbox to\z@{\mydotleader{.4ex}\hskip\@pnumwidth\kern\z@\hss},
+% subsection/skip=-.7ptplus.01fil,
+% section/skip=2ptplus.01fil,
+% after=\vspace*{-6pt}\leavevmode\mydotleader{0pt}\hfill\kern\z@,
+% columns=2,
+% multicolsep=0pt,
+% bookmark={bold,text=etextools,color=black},
+% }
+% \colorlet{reflink}{DarkSlateBlue}^^A\definecolor{reflink}{rgb}{0.37,0.00,0.37}
+% \tableofcontents
+% \endgroup
+% \OnlyDescription
+%
+% \vskip-6pt\begin{shaded}\parindent0pt\noindent\normalsize\topsep=-\parskip\itemsep=-\parskip
+% \let\reflink\reflinkabstract
+%
+% {\bfseries\catcode`\ \active\let =\,\hfil\NibSolidRight¤¤\raise3pt\hbox{ A b s t r a c t }¤¤\NibSolidLeft\hfil}\par
+%
+% The \thispackage package is based on the \xpackage{etex} and \xpackage{etoolbox}
+% packages and defines a lot of macros for \LaTeX\ Users or package Writers.
+% Before using this package, it is highly recommended to read the
+% documentation (of this package and...) of the \xpackage{etoolbox} package.
+%
+% This package requires the \xpackage{etex} package from David Carlisle
+% and the \xpackage{etoolbox} package from Philipp Lehman.
+% They are available on CTAN under the \sty{/latex/contrib/} directory \footnotemark.
+%
+% \underline{\bfseries The main contributions of \thispackage are :}\hfill\smex\hyperref{}{Part}{ListOfCommands}{\blue see the complete list}
+% \begin{itemize}
+% \item \cmdref{expandnext}: a vectorized form of \csbf{expandafter} and \cmdref{ExpandNext} that works like
+% \cs{expandnext} but expands infinitely (with \cmdref{expandaftercmds} and \cmdref{ExpandAftercmds})
+% \item a \hyperref{}{cmdlabel}{DeclareStringFilter}{\underline{\vb\reflink String-Filter constructor}}
+% to compare strings in a purely expandable way and many other macros on strings among them \cmdref{ifstrnum}
+% \item \cmdref{futuredef}: a macro (and vectorized) version of \CSbf{futurelet}.
+% \item the ability to define fully expandable macros with optional parameters or star form (with a small restriction)
+% -- \cmdref{FE@testopt}, \cmdref{FE@ifstar}, \cmdref{FE@ifchar} and \cmdref{FE@modifiers}
+% \item a Command-List Parser constructor that uses those new features: command-list parsers are fully expandable:
+% \cmdref{csvloop}, \cmdref{listloop}, \cmdref{toksloop}, \cmdref{naturalloop} and more...
+% \end{itemize}
+% \end{shaded}
+% \footnotetext{This documentation is produced with the \xpackage{ltxdockit}
+% classe and package by Philipp Lehman using the |DocStrip| utility.
+% \begin{tabbing}
+% \qquad\=\smex\=To get the documentation, \= run (twice):\quad\= \sty{pdflatex etextools.dtx} \\
+% \>\smex\>To get the package, \> run:\> \sty{etex etextools.dtx}
+% \end{tabbing}
+% The .dtx file is embeded in this pdf thank to \xpackage{embedfile} by H. Oberdiek.\vskip0ptplus1filll}
+%
+% ^^A END OF FIRST PAGE ----------------------------------------------------------------------------------------------
+% \vfil\break
+% \endgroup
+%
+% ^^A\stop
+% \begingroup \movepage{1cm}\footskip=0pt\enlargethispage{\baselineskip}
+% \Section*{Introduction}
+% \addcontentsline{toc}{section}{\hskip\cftsecnumwidth\texorpdfstring\dr{} Introduction}
+% \renewcommand\thesubsection{\arabic{subsection}}^^A for toc
+%
+% \Subsection{Motivation}
+%
+% The first motivation for this package was to define a powerful list-parser macro that enhance the one
+% provided by \xpackage{etoolbox}. Loops are a basic in programming, and the need for them comes sooner or
+% later when using \LaTeX.
+%
+% As a result, a lot of ``derived'' macro have been build, their definition and name carefully chosen...
+% For exemple, removing an element in a list is the same as removing a substring in a string, and then
+% quite the same as testing if two strings are equal...
+%
+% Finally, \thispackage provides a lot a tools to make definitions of new commands more flexible (modifiers...)
+% maintain list for special purpose (like the lists of purely expandable macros in this very pdf document),
+% to get rid of catcode considerations when dealing with characters (the \emph{character-test}): the list of (nearly all)
+% commands defined by \thispackage lies on next page...
+%
+% \Subsection{Purely Expandable macros}
+%
+% A \textbf{purely expandable command} is a command whose expected result can be obtained in an |\edef|.
+% They can also be placed inside |\csname|...|\endcsname|, and are totally expanded after
+% |\if|, |\ifnum|, |\ifcase|, |\ifcat|, |\number|, |\romannumeral|.
+%
+% The\FE fully expandable (or purely expandable) commands defined in \thispackage
+% can be easily spotted with the special marker displayed here in the margin for information.
+%
+% A purely expandable macro may require one, two or many more \textbf{levels of expansion} in order
+% to reach its goal. Such macros that expands to the expected result at once\FEI are marked with the
+% special sign displayed here in the \textsf{marginpar}. And such macros that requires only two levels
+% of expansions are marked with the special sign displayed here\FEII in the \textsf{marginpar}.
+%
+% {\centering
+% \begin{tabu}{|>{\rred}X[-1c]|X|} \hline
+% \thead{levels} & \thead{sequence to get the result} \\ \tabucline-
+% $\mathbf1$ & \cs[\red]{expandnext}\M*{\cs{def}\cs{result}}\M*{\cs[\copper]{FEmacro}\mprm{arguments}} \\ \tabucline[on 1pt off1pt]-
+% $\mathbf2$ & \cs[\red]{expandnext}\cs[\red]{expandnext}\M*{\cs{def}\cs{result}}\M*{\cs[\copper]{FEmacro}\mprm{arguments}} \\ \tabucline[on 1pt off1pt]-
+% more & \cs[\red]{ExpandNext}\M*{\cs{def}\cs{result}}\M*{\cs[\copper]{FEmacro}\mprm{arguments}} \footnotemark \\ \tabucline-
+% \end{tabu}\par}
+% \footnotetext{\cs{ExpandNext} is not always enough: \cs{csvloop} for exemple requires \cs{edef} (or \cs{csname}...) to be completely expanded.}
+%
+% A few\pdfFE macros are only expandable if the |\pdfstrcmp| (or |\strcmp|) primitives are available
+% ^^A(this is notably the case of \cmdref{getlistindex}).
+% Those macros are marked with the special marker displayed here in the margin for information.
+%
+% \Subsection{The example file}
+%
+% The \hyperref{file:etextools-examples}{ettlex}{toc}{example file} provided with \thispackage\ illustrates the macros defined here.
+%
+% \Subsection{Requirements}
+%
+% This package requires the packages \Xpackage[etex-pkg]{etex} by David Carlisle and
+% \Xpackage{etoolbox} by Philipp Lehman. The \cmdref{aftergroup@def} macro uses the feature provided
+% by \Xpackage[oberdiek/letltxmacro]{letltxmacro} by Heiko Oberdiek.
+%
+% \Subsection{Acknowledgements -- Thank You !}
+%
+% Thanks to Philipp Lehman for the \xpackage{etoolbox} package (and also for this nice class of documentation).
+% Much of my work on lists are based on his work and package.
+%
+% \Subsection{A note for package writers}
+%
+% If you are interested in writing your own purely expandable macros (using the features of \thispackage...)
+% it's important to know well the basics: you must understand the job of \cmdref[impl:ettl@nbk]{ettl@nbk} and \cs{romannumeral},
+% and take a lot of care of malicious spaces.
+% \vfill
+% {\hfill\spot\usefont{T1}{txss}{b}{n}\LARGE\raise1.5ex\hbox{\scalebox{1}[-1]\Lightning}\kern14pt Happy \eTeX ing\kern12pt\raise1.5ex\hbox{\scalebox{-1}[-1]\Lightning}\hfill}
+% \vfill\clearpage
+% \endgroup \normalsubsecformat
+%
+% \begingroup\makeatletter \movepage[-2cm]{2.5cm}\enlargethispage{2\baselineskip}
+% \colorlet{reflink}{MidnightBlue}
+% \listofsetup{cmds}{
+% command/number/width=1.5em,
+% command/leader=\cftsubsecleader,
+% command/font=\large\sfbf\db,
+% before=,
+% title/font=\vspace*{-4mm}\LARGE\bfseries,
+% title=\mydotleader{.4ex}\hfill\kern.5em
+% \hyperdef{Part}{ListOfCommands}{\begin{tabu}[b]{c} \thispackage\\[-1ex] List of Commands Provided\end{tabu}}^^A
+% \kern.5em\mydotleader{.4ex}\hfill,
+% title/bottom=12pt,
+% command/skip=4pt plus.1fil,
+% pagestyle=empty,
+% bookmark={bold,color=blue,text=List of commands,level=0},
+% multicols/after=\aftergroup\theleader,
+% twocolumns,
+% }
+% \def\theleader{\vspace*{-3mm}\mydotleader{-.4ex}\hfill\kern0pt}
+% \listofcommand
+% \clearpage
+% \endgroup
+%
+% \part*{{\spot\blacksmiley}\hfill All User Commands\hfill{\spot\blacksmiley}}
+%
+% \bookmarksetup{openlevel=1}
+%
+% \Section{General Helper Macros}
+%
+% \begin{ltxsyntax}
+%
+% \cmditem{@gobblespace}{ code }
+%
+% This macro\FEI first gobbles the next space token and then expands the \prm{code}.
+% Truly, a ``space token'' means any character of category $10$.
+%
+% \cmditem{@gobblescape}
+%
+% Just gobble\FEII the first character on the result of \cmd{string} (escape character).
+%
+% {\rmk \cs{@gobblescape} is used in the definition of \cmdref{DeclareStringFilter}, \cmdref{DeclareCmdListParser} and
+% for the general constructor to remove elements from lists (\cs{listdel} etc.): \cmdref*{ettl@RemoveInList}.}
+%
+% \cmditem[@swap]+@{@swap\tsptb @swaparg\tsptb @swaplast}
+% \cmditem-{@swap}{ token1 }{ token2 }
+%
+% Just\FEI reverse the order of the two tokens:\hfill \cs[\red]{@swap}\#1\#2| |\smex\#2\#1.
+%
+% \CSbf{@swap} does not add any curly braces (be aware that it does not remove them, however).
+%
+% \csbf{@swap} is so simple that it requires a special attention: \cs{@swap} is powerful...§§
+% \begin{VerbLines}[commandchars=!()]
+% (!red\@swap){ }\meaning !smex blank space
+% \expandafter(!red\@swap)\expandafter{!PRM[!copper](codeA)}{!PRM[!copper](codeB)}
+% !nnn will expand !PRM[!copper](codeA) once and the put !PRM[!copper](codeB) just before
+% \end{VerbLines}
+%
+% {\rmk \cs{@swap} is used in the definitions of \cmdref{expandaftercmds} and \cmdref{protectspace}.}
+%
+% \cmditem-{@swaparg}{ code }{ command }
+%
+% Just\FEI make \prm{code} the first argument of \prm{command}:\hfill \cs[\red]{@swaparg}\#1\#2| |\smex\#2|{|\#1|}|.
+%
+% {\rmk \cmd{@swaparg} is used in the definition of \cmdref{expandnext}}.
+%
+% \cmditem-{@swaplast}{ token1 }{ token2 }{ token3 }
+%
+% \CSbf{@swaplast}\FEI swaps \prm{token2} and \prm{token3} but \prm{token1} remains in first position:§
+% \hfill \cs[\red]{@swaplast}\#1\#2\#3| |\smex| |\#1\#3\#2
+%
+% {\rmk \cs{@swaplast} is used in the definition of the command-list-parser defined with \cmdref{DeclareCmdListParser}.}
+%
+% \cmditem{@swaptwo}{ token1 }{ token2 }
+%
+% Just\FEI reverse the order of the \textbfsf{arguments:}\hfill \cs[\red]{@swaptwo}\#1\#2| |\smex|{|\#2|}{|\#1|}|.
+%
+% \CSbf{@swaptwo} keeps the curly braces around its arguments (be aware that it does not add them, however).
+%
+% {\rmk \cmd{@swaptwo} is used in the definition of \cmdref{gettokslistindex} and \cmdref{getcharlistindex}.}
+%
+% \end{ltxsyntax}
+%
+% \Section{Expansion control}
+%
+% We often want a control sequence to be expanded after its first argument. It is normally the job
+% of \cs{expandafter}. With many \cs{expandafter}s it is always possible to expand once, twice, thrice
+% or more, the \textbfsf{very first token that occurs after the begin-group character} delimiting the argument.
+%
+% \cmdref{expandnext} simplifies the syntax (without making the execution process too heavy).
+%
+% Now it is also possible to expand the \textsfsl{very first} token \textsfbf{infinitely}:
+% this is the aim of \cmdref{ExpandNext}.
+%
+% \begin{ltxsyntax}
+% \ClearPage*
+% \cmditem+{expandaftercmds}{ code }{ control sequences }
+%
+% \csbf{expandafter}\FE is sometimes limited because it affects only the very next token.
+% \csbf{expandaftercmds} works just like the \csbf{expandafter} primitive but may be followed by
+% arbitrary \prm{code}, not only a single token.
+%
+% A typical example is the following code, which detokenizes the character \CH{\#{}}:§
+% \begin{VerbLines}[commandchars=!()]
+% (!red\expandaftercmds{)\expandafter\@gobble\string(!red}){\csname !#\endcsname}
+% \end{VerbLines}
+% without duplication (|\detokenize{|\#{}|}| leads to \CH{\#{}\#{}} if catcode of \#{} is $6$)
+%
+% {\rmk \cs{expandaftercmds} is used in the definition of \cs{ettl@Remove} and then in
+% \cmdref{listdel}, and the string-comparators declared with \cmdref{DeclareStringFilter}}.
+%
+% \cmditem+{expandnext}{ code }{ control sequences }
+%
+% \CSbf{expandnext}\FE is quite the same as \CSbf{expandaftercmds} except that the \prm{control sequences}
+% are the \textbfsf{argument of} \prmb{code}, \ie they are enclosed with curly braces after expansion.
+%
+% Suppose you want to test if the replacement text of a macro is blank (only spaces). You will say:§§
+% \begin{VerbLines}[commandchars=!()]
+% (!blue\expandafter)(!copper\ifblank)(!blue\expandafter) {\foo}{!prm(true part)}{!prm(false part)}
+% !normalfont(With !cs(expandnext) you'll just have to say:)
+% (!red\expandnext)(!copper\ifblank){\foo}{!prm(true part)}{!prm(false part)}
+% \end{VerbLines}
+%
+%
+% \textbfsf{\prmb{code} may be arbitrarily \TeX{} code, unlike \CSbf{expandafter},} you may say:§§
+% \begin{VerbLines}[commandchars=!()]
+% (!red\expandnext{)(!copper\def\test)(!red}){\csname name\endcsname} !hfil!nsl and it is exactly:
+% !mdseries\edef\test{\expandafter\noexpand\csname name\endcsname}
+% !nsl and also exactly:
+% !mdseries!small \expandafter\def\expandafter\test\expandafter{\csname name\endcsname}
+% (!mdseries!normalfont!itshape Genauer gesagt:) \meaning\test = macro:->\name
+% \end{VerbLines}
+%
+% \csbf{expandnext} can be used for macros with optional arguments:§§
+% \begin{VerbLines}[commandchars=$()]
+% ($red expandnext{)($copper\Macro[option])($red}){$prm(argument)}
+%\end{VerbLines}
+%
+% \csbf{expandnext} can be used to test if a purely expandable macro is expandable at once.
+% (If it is not, the \cmdref{ExpandNext} macro can be used intead.)
+%
+% Now \csbf{expandnext} behaves like \cs{expandafter} and is cumulative: if you need two levels
+% of expansions you may say:§§
+% \begin{VerbLines}[commandchars=!()]
+% (!red\expandnext\expandnext)(!copper{\def\test}){\csname name\endcsname}
+% !normalfont and it is exactly:
+% !mdseries!small\edef\test{\expandafter\expandafter\expandafter\noexpand\csname name\endcsname}
+% !normalfont and also exactly:
+% !mdfs\expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter\test
+% !mdfs \expandafter\expandafter\expandafter{\csname name\endcsname}
+% (!mdseries!normalfont!emph(Genauer gesagt:)) \meaning\test = macro:-> !prmb(the meaning of !csbf(name))
+% \end{VerbLines}
+% \cs{expandnext} is an \cs{expandafter} saver !
+%
+% {\rmk
+% Now observe the following game :
+% \begin{tabbing}
+% \qquad\= |\def\foo{foo}| \qquad \= \smex \qquad \= |\def\Foo{\foo}| \quad \= \eol \\
+% \> |\def\\FOo{\Foo}| \> \smex \> |\def\FOO{\FOo}| \> \eol \\
+% \> |\def\fool{\FOO}|
+% \end{tabbing}
+% Guess how many \cmd{expandafter} are needed to test ``|\ifblank{foo}|'' directly from |\fool| ???
+%
+% |\expandnext| solves this problem : |\fool| has 5 degrees of expansion until it expands to ``foo'', therefore exactly 5
+% |\expandnext| are required. The solution is:§
+% \qquad |\expandnext\expandnext\expandnext\expandnext\expandnext\ifblank{\fool}|}
+%
+% \cmditem{expandnexttwo}{ code }{ control sequences }{ control sequences }
+%
+% \csbf{expandnexttwo}\FE will act as \cs{expandnext} on two arguments:
+%
+% \qquad\cs{expandnexttwo}:\enspace\#1\#2\#3$\longrightarrow$
+% \cs{expandnext} {\textbf\{}\cs{expandnext}\{\#1\}\Underbrace{\{\#2\}}_{\scriptsize\makecellbox[c]{expanded\\\bfseries once after}}\textbf\}\Underbrace{\{\#3\}}_{\scriptsize\makecellbox[c]{expanded\\\bfseries once first}}
+%
+% You may easily define \cs{expandnextthree} the same way, if you need it...
+%
+% {\rmk \cs{expandnexttwo} is used in \cmdref{iffirstchar}.}
+%
+% \cmditem{ExpandAftercmds}{ code }{ control sequences }
+%
+% \csbf{ExpandAftercmds}\FE acts like the primitive \cs{expandafter} but:\enlargethispage{\baselineskip}
+% \begin{enumerate}[label=--~]
+% \item the \textslsf{very first} token in \prmb{control sequences} is \textbfsf{totally expanded}
+% \item \prmb{code} may be arbitrarily code (not necessarily a single token)
+% \end{enumerate}
+%
+% \ClearPage
+% \cmditem+{ExpandNext}{ code }{ control sequences }
+%
+% More\FE on expansion! Suppose you have a string say "12345"\ and you wish to reverse the order of
+% the letters (here, the \textit{figures}). To do that we need a macro that swaps two elements, and then
+% group them in order to swap with the next in a loop: the idea is to do:
+% \quad |12345|\smex swap |{21}345| \smex swap |{321}45| \smex swap |{4321}5|.
+%
+% \thispackage provides a tool to loop against natural integers from $1$ to $n$. \cmdref{naturalloop}
+% is purely expandable and we get the result with:§
+% \begin{VerbLines}[commandchars=!(),fontseries=m]
+% \def\swap!#1!#2{{!#2!#1}}
+% \def\do[!#1]!#2!#3{\swap !#3}
+% (!bfseries\edef\result{\naturalloop[\do]{4}{12345}} !smex macro:->54321)
+% (!bfseries(!red\ExpandNext{)(!copper\def\RESULT)(!red }){\naturalloop{4}{12345}}!smex:->54321)
+% \end{VerbLines}
+%
+% \textbfsf{\CSbf{ExpandNext} has expanded the second argument totally without the use of \CSbf{edef}!}
+%
+% In fact, it is possible because \CSbf{naturalloop} is defined in terms of \CSbf{ExpandNext}.
+%
+% {\rmk \cs{ExpandNext} is used in the definition of \cmdref{naturalloop} and \cmdref{DeclareStringFilter}.}
+%
+% \cmditem+{ExpandNextTwo}{ code }{ arg1 }{ arg2 }
+%
+% \cs{ExpandNextTwo}\FE will act like \cs{ExpandNext} on two arguments:
+%
+% \qquad\cs{ExpandNextTwo}:\enspace\#1\#2\#3$\longrightarrow$
+% \cs{ExpandNext} {\textbf\{}\cs{ExpandNext}\{\#1\}\Underbrace{\{\#2\}}_{\scriptsize\makecellbox[c]{totally\\expanded\\\bfseries after}}\textbf\}\Underbrace{\{\#3\}}_{\scriptsize\makecellbox[c]{totally\\expanded\\\bfseries first}}
+%
+% You may easily define \cs{ExpandNextThree} the same way, if you need it...
+%
+% {\rmk \cs{ExpandNextTwo} is used in the final step of \cmdref{gettokslistindex} and \cmdref{getcharlistindex}.}
+%
+%
+% \cmditem{noexpandcs}{ csname }
+%
+% In an \FEI expansion context (|\edef|) we often want a control sequence whose name results
+% from the expansion of some macros and/or other tokens to be created, but not expanded at that point.
+% Roughly:§
+% \qquad |\edef{\noexpandcs{<balanced text to be expanded as a cs-name>}}|§
+% will expand to: |\"cs-name"| but this (new) control sequence itself will not be expanded.
+% A typical use is shown in the following code:§
+% \smex |\edef\abc{\noexpandcs{abc@\@gobblescape\controlword}}|§
+% \smex if equivalent to:\quad|\def\abc{\abc@controlword}|.
+%
+% {\hint|\noexpandcs| may be abbreviated f.ex. in |\"#1"| in |\edef| that take place in a group. }
+%
+% \cmditem{noexpandafter}
+%
+% |\noexpandafter|\FEI only means |\noexpand\expandafter| and is shorter to type.
+%
+% {\rmk This command is used in the definition of \cmdref{DeclareCmdListParser}.}
+%
+% \end{ltxsyntax}
+%
+% \ClearPage*
+% \Section[Meaning of control sequences]{Meaning of control sequences -- determining their type.}
+%
+% \begin{ltxsyntax}
+%
+% \cmditem+{thefontname}
+%
+% \csbf{thefontname}\notFE will display (in Computer Modern font at 10 points) the name of the current font selected.
+% Something like:§
+% \qquad|select font musix11 at 10.0pt|
+%
+% \cmditem[showcs]@{showcs \tsptb showthecs}
+% \cmditem-{showcs}{ csname }
+%
+% \cs{showcs}\notFE does \cs{show} on the named control sequence.
+%
+% \cmditem-{showthecs}{ csname }
+%
+% \cs{showthecs}\notFE does \cs{showthe} on the named control sequence.
+%
+% \cmditem{meaningcs}{ csname }
+%
+% \cs{meaningcs}\FEII gives the \cs{meaning} of the named control sequence. However, if the control sequence is
+% not defined, \cs{meaningcs} expands to |\meaning\@undefined| (\ie the word \CH{undefined}) rather than the expected |\relax|.
+%
+% \cmditem{strip@meaning}{ cs-token }
+% \cmditem*{strip@meaningcs}{ csname } \FEII*
+%
+% \csbf{strip@meaning}\FEII gives the \cs{meaning} of the \prm{cs-token}:
+% \begin{enumerate}[label=\roman*)~]
+% \item without the prefix `\,|macro:|\#1\#2...|->|)\,` ¤ if \prm{cs-token} is a macro
+% \item integrally if \prm{cs-token} is defined and is not a macro
+% \item expands to an empty string if \prm{cs-token} is undefined.
+% \end{enumerate}
+%
+% \cs{strip@meaningcs} does the same for named control sequences.
+%
+% \cmditem{parameters@meaning}{ cs-token }
+% \cmditem*{parameters@meaningcs}{ csname } \FEII*
+%
+% \csbf{parameters@meaning}\FEII expands to the part of the \cs{meaning} which corresponds
+% to the \textitbf{parameter string}. If a macro has no parameter, then it expands to an empty string.
+% If the \prm{cs-token} or the \prm{csname} given is not a macro, it also expands to an empty string.
+%
+% \newcommand*\mycell{\small\makecell[c]} \newcommand*\macpf{\vb macro:} \let\theadfont=\nbf
+% \hskip-1.5em\begin{tabular}{|>{\vb\cs{}}l|c|c|c|}\hline
+% \multicolumn{4}{c}{\textbfbf{to summarize}} \\ \hline
+% \omit & \omit & \omit & \omit \\ [.3ex] \cline{2-4}
+% \multicolumn{1}{l|}{} & \thead{macro} & \thead{not macro} & \thead{undefined} \\ \hline
+% meaning & \mycell{the meaning \\ \eg \macpf[\#1]\#2->\#1\#2} & \mycell{the meaning \\ \eg \cs{count21}} & \vb undefined \\
+% meaningcs & \mycell{the meaning \\ \eg \macpf[\#1]\#2->\#1\#2} & \mycell{the meaning \\ \eg \cs{count21}} & \vb undefined \\ \hdashline[1pt/1pt]
+% strip@meaning & \mycell{the replacement text \\ \eg \#1\#2} & \mycell{the meaning \\ \eg\cs{count21}} & an empty string \\
+% strip@meaningcs & \mycell{the replacement text \\ \eg \#1\#2} & \mycell{the meaning \\ \eg\cs{count21}} & an empty string \\ \hdashline[1pt/1pt]
+% parameters@meaning & \mycell{the parameter string \\ \eg[\#1]\#2} & an empty string & an empty string \\
+% parameters@meaningcs & \mycell{the parameter string \\ \eg[\#1]\#2} & an empty string & an empty string \\ \hline
+% \end{tabular}
+% \ClearPage*
+%
+% \cmditem{ifdefcount}{ single token }{ true }{ false }
+% \cmditem*{ifdeftoks}{ single token }{ true }{ false } \FEII*
+% \cmditem[ifdefskip]@{ifdefdimen\tsptb ifdefskip\tsptb ifdefmuskip}
+% \cmditem-{ifdefdimen} {cs-token }{ true }{ false } \FEII*
+% \cmditem-{ifdefskip}{ single token }{ true }{ false } \FEII*
+% \cmditem-{ifdefmuskip}{ single token }{ true }{ false } \FEII*
+% \cmditem[ifdefchar]@{ifdefchar\tsptb ifdefmathchar}
+% \cmditem-{ifdefchar}{ single token }{ true }{ false } \FEII*
+% \cmditem-{ifdefmathchar}{ single token }{ true }{ false } \FEII*
+%
+% \xpackage{etoolbox}\FEII provides \cs{ifdefmaco} to test if a given control sequence is defined as a macro.
+% \thispackage provides tests for other types of tokens.
+%
+% Test is made by a filter on the meaning of the \prm{single token} given as argument. The test is always false
+% if this \prm{single token} is an undefined control sequence.
+% \iffalse
+% \cs{ifdefblankspace} will expand \prm{true} if the \prm{single token} is a blank space.§
+% \cs{ifdefthechar} will expand \prm{true} is the \prm{single token} has a meaning of the form: |the character|\stform[\blue]\textellipsis§
+% \cs{ifdeftheletter} will expand \prm{true} is the \prm{single token} has a meaning of the form: |the letter|\stform[\blue]\textellipsis§
+%
+% {\rmk \cs{ifdefcount} is used -- indirectly -- in the definition of \cmdref{getlistindex} and the other macros
+% for getting indexes: \cmdref{getcsvlistindex} etc.}
+% \fi
+% \ClearPage
+%
+% \cmditem[avoidvoid]+@{avoidvoid \tsptb avoidvoidcs}
+% \cmditem-{avoidvoid} [ replacement code ]{ cs-token / string } \FEII*
+% \cmditem-{avoidvoid\stform*}[ replacement code ]{ cs-token / string } \FEII*
+%
+% \csbf{avoidvoid}\FEII will test the \prm{cs-token} with \cs{ifdefvoid} (from \xpackage{etoolbox}). In case
+% \prm{cs-token} is void (that means: it is either undefined or has been |\let| to |\relax| or it is a parameterless macro
+% with blank -- \ie empty or space -- replacement string), then \cs{avoidvoid} expands \prm{replacement code}
+% (optional parameter whose default is an empty string).
+%
+% Otherwise, \prm{cs-token} is not void (that means: it is defined, its meaning is not |\relax| AND it is either
+% a macro with parameters or a parameterless macro with a replacement string which is NOT blank)
+% then \cs{avoidvoid} expands \prm{cs-token}:§§
+% \begin{VerbLines}[commandchars=$()]
+% ($red\avoidvoid) {\@undefined} ($nnn will expand to an empty string)
+% ($red\avoidvoid) [($copper\macro)]\relax ($nnn will expand) ($md$copper\macro)
+% ($red\avoidvoid) [($copper$!$!$! string is blank)]{$spview} ($nnn will expand$vb$copper string is blank)
+% ($red\avoidvoid$stform*)[($copper$!$!$! string is empty)]{$spview} ($nnn will expand $spview)
+% ($red\avoidvoid) [($copper\errmessage{string must not be empty})]{some text}
+% ($nnn will expand$vb some text)
+% ($red\avoidvoid) [($copper\errmessage{macro is void$})]\macro
+% ($nnn will expand ($vb$copper\errmessage{...}) if ($vb\macro) is void)
+% \protected\def($dg\test){$spview}
+% \edef($copper\result){($red\avoidvoid$stform*)($dg\test)}
+% \meaning($copper\result) macro:->($dg\test) ($nnn1-expansion of ($dg\test) not empty)
+% \edef($copper\result){($red\avoidvoid)[other]($dg\test)}
+% \meaning($copper\result) macro:->other ($nnn1-expansion of ($dg\test) is blank)
+% \end{VerbLines}
+%
+% \cs{avoidvoid} is based on \cs{ifblank} test, either onto \prm{string} or, if \prm{string} is in fact a
+% control word (tested with \cmdref{ifiscs}) on the replacement text of this control word\footnote{if it is defined
+% as a macro. Well: the test occurs on the result of \cmdref{strip@meaning} onto the control-sequence!}. If for your
+% special purpose, you prefer to test if the \prm{string} (or the replacement text of \prm{cs-token}) is \textbfsf{really empty
+% and not only blank}, the \stform* star-form of \cs{avoidvoid} is made for you!
+%
+% \cs{avoidvoid} is purely expandable and uses \cmdref{FE@ifstar} and \cmdref{FE@testopt}:
+% if the mandatory argument is a \prm{string} equal to \CH{\stform[\blue]*$__{12}$} or \CH{\stform[\blue][$__{12}$}^^A]
+% there will be a problem (and most probably an error). Therefore, \textbfsf{when using \csbf{avoidvoid} you are encourage to
+% specify always an option, even if it is empty.}
+% \ClearPage*
+% \cmditem-{avoidvoidcs} [ replacement code ]{ csname } \FEII*
+% \cmditem-{avoidvoidcs\stform*}[ replacement code ]{ csname } \FEII*
+%
+% \csbf{avoidvoidcs}\FEII will do the same as the former (\cs{avoidvoid}) but the mandatory argument \prm{csname}
+% is interpreted as a control sequence name. \enlargethispage\baselineskip
+% Therefore, \textbfsf{you cannot test a \textvbbf{string} with \csbf{avoidvoidcs}!}§§
+% \begin{VerbLines}[commandchars=$()]
+% ($red\avoidvoidcs){@undefined} ($nnn will expand to an empty string)
+% ($red\avoidvoidcs)[\deblank]{zap@space} ($nnn will expand to $cs(zap@space))
+% \def($dg\test){This is a test}
+% ($red\avoidvoidcs)[($copper\errmessage{void macro})]{test}
+% ($nnn will expand) $dg\test
+% ($red\avoidvoidcs)[($copper\errmessage{void macro})]{($dg\test)}
+% ($nnn will expand) ($md$copper\errmessage{void macro})
+% ($nnn this is because) \csname This is a test\endcsname($nnn is not defined !)
+% ($nbf Finally, clever !)
+% \protected\def($dg\test){$spview}
+% ($red\avoidvoidcs) [other]{test} ($nnn will expand) other ($nnn: $cs(test) is void)
+% ($red\avoidvoidcs*)[other]{test} ($nnn will expand) ($dg\test) ($nnn: $cs(test) is not $cs(@empty))
+% ($red\avoidvoidcs) [other]($dg\test) ($nnn will expand) \ ($nnn: control space, which is not void)
+% ($red\avoidvoidcs*)[other]($dg\test) ($nnn will expand) \ ($nnn: control space, which is not void)
+%\end{VerbLines}
+%
+% \end{ltxsyntax}
+% \ClearPage*
+%
+% \Section{Single tokens/single characters}
+%
+% A single token is either a control word (that means a caracter of category $0$ followed by caracters of category $11$)
+% or a single character with a valid category code (\ie $\ne 15$ and $\ne 9$).
+%
+%
+% \Subsection{The \cs{ifx} test and the character test}
+% \cmdlabel{character-test}
+%
+% When dealing with single tokens, we need an \emph{equality-test} macro that expands to |\@firstoftwo| in case of
+% equality and |\@secondoftwo| in case of inequality.
+%
+% \thispackage implements two such \textbfsf{\slshape equality-test macros}:
+%
+% \begin{enumerate}[label={\blue\arabic*)~}]
+% \item The \csbf[\blue]{ifx} test: is the standard test for tokens:\\
+% \null¤¤\prm{tokenA} is equal to \prm{tokenB} if:¤¤ {\rred\cs{ifx}\PRM[\black]{tokenA}\PRM[\black]{tokenB}}¤ returns \textbf{true}\\
+% {\rmk* The \csbf{ifx} test is implemented in \cmdref*{ettl@ifx}.}
+% \item The \textbfsf{\blue character test} is a bit more sophisticated and works as follow:§
+% \begin{enumerate}[label=\roman*)~,labelwidth=1em]
+% \item if \prm{tokenA} and \prm{tokenB} have the same category code (tested with an unexpandable |\ifcat|):\\
+% \prm{tokenA} is equal to \prm{tokenB} if:¤¤ {\rred\cs{ifx}\PRM[\black]{tokenA}\PRM[\black]{tokenB}}¤ returns \textbf{true}
+% \item otherwise:\\
+% \prm{tokenA} is equal to \prm{tokenB} if:¤{\rred\cs{if}\cs{noexpand}\PRM[\black]{tokenB}\cs{string}\PRM[\black]{tokenA}}\\
+% \null\hphantom{\prm{tokenA} is equal to \prm{tokenB} if:¤¤ {\rred\cs{ifx}\PRM[\black]{tokenA}\PRM[\black]{tokenB}}¤} returns \textbf{true}
+% \end{enumerate}\vskip-\parskip
+% {\rmk* The \textbfsf{character test} is implemented in \cmdref*{ettl@ifchar} and its behaviour may be tested with \cmdref{ifsinglechar}.}
+% \end{enumerate}
+%
+% \Subsection.{Basic test macros}
+%
+% \begin{ltxsyntax}
+%
+% \cmditem[ifsingletoken]+@{ifsingletoken~\db\tsptb ifOneToken}
+% \cmditem-{ifsingletoken}{ single token }{ code }{ true }{ false }
+%
+% \csbf{ifsingletoken}\FEII expands to \prm{true} only if \textsfbf{\prmb{code} is a single token and is equal
+% to \prmb{single token} in the sense of \cs{ifx}.}
+%
+% \cs{ifsingletoken} is a \textbfsf{safe \cs{ifx} test}: \prm{code} may be anything (including |\if| conditionals,
+% even not properly closed):§§
+% \begin{VerbLines}[commandchars=$()]
+% ($red\ifsingletoken){A}{A} $nnn will expand $prmb(true)
+% ($red\ifsingletoken){\else}{($blue$textvisiblespace)\else}$nnn will expand $prmb(false)
+% ($red\ifsingletoken){($blue$textvisiblespace)}{($blue$textvisiblespace)} $nnn will expand $prmb(true)
+% ($red\ifsingletoken){\ifx}{\else D\fi} $nnn will expand $prmb(false)
+% ($red\ifsingletoken){}$mprm( whatever ) $nnn will expand $prmb(true) only if $prmb(whatever) is empty !!
+% $md$dg \begingroup\catcode`\: 13\global\def($copper\test){:}\endgroup \catcode`\: 12
+% \expandnext($red\ifsingletoken){($copper\test)}{:} $nnn will expand $prmb(false)
+%$nnn$!$!$!now clever !
+% $md$dg\begingroup\catcode`\: 13 \global\let$stform[$blue]:=\fi \gdef($copper\test){($red\ifsingletoken) $stform[$blue]:}
+% $md$dg\endgroup
+% ($copper\test)\fi$mprm(true)$mprm(false) $nnn will expand $prmb(true)
+% \end{VerbLines}
+%
+% Be aware that \prm{single token} (the first parameter) must be a single token (or empty, but then the test is always false unless \prm{code} is empty).
+%
+% \ClearPage
+% \cmditem-{ifOneToken}{ code }{ true }{ false }
+%
+% \csbf{ifOneToken}\FEII expands to \prm{true} if \textbfsf{\prmb{code} is a single token}. \prm{code} may be
+% anything (including |\if| conditionals, even not properly closed):§§
+% \begin{VerbLines}[commandchars=$()]
+% ($red\ifOneToken){\relax}{($blue$textvisiblespace)\relax} $nnn will expand $prmb(false)
+% ($red\ifOneToken){\relax}{\relax($blue$textvisiblespace)} $nnn will expand $prmb(true)
+% ($red\ifOneToken){A}{A($blue$textvisiblespace)} $nnn will expand $prmb(false)
+% ($red\ifOneToken){\ifx AB C\else D\fi} $nnn will expand $prmb(false)
+% ($red\ifOneToken){C\else D\fi} $nnn will expand $prmb(false)
+% \end{VerbLines}
+%
+% {\rmk \cs{ifOneToken} is used in the definition of \cmdref{FE@modifiers}.}
+%
+% \ClearPage
+% \cmditem[ifsinglechar]+@{ifsinglechar~\db\tsptb ifOneChar}
+% \cmditem-{ifsinglechar}{ single token }{ string }{ true }{ false }
+%
+% \csbf{ifsinglechar}\FEII expands to \prm{true} only if \textbfsf{\prmb{string} is a single token and is equal
+% to \prmb{single token} in the sense of the \cmdref={character-test}.}
+%
+% \cs{ifsinglechar} is a \textbfsf{safe \slshape character-test}: \prm{string} may be anything (including |\if| conditionals,
+% even not properly closed):§§
+% \begin{VerbLines}[commandchars=$()]
+% ($red\ifsinglechar){A}{A} $nnn will expand $prmb(true)
+% ($red\ifsinglechar){A}{($blue$textvisiblespace)A} $nnn will expand $prmb(false)
+% ($red\ifsinglechar){($blue$textvisiblespace)}{($blue$textvisiblespace)} $nnn will expand $prmb(true) (no matter the number of spaces)
+% ($red\ifsinglechar){\ifx}{\ifx\test\relax YES\else NO\fi} $nnn will expand $prmb(false)
+% ($red\ifsinglechar){}$mprm( whatever )$nnn will expand $prmb(true) only if $prmb(whatever) is empty
+% ($red\ifsinglechar){\scantokens}{\scantokens} $nnn will expand $prmb(true)
+% $vbmd$dg\begingroup\catcode`\: 13\global\def($copper\test){:}\endgroup \catcode`\: 12
+% \expandnext($red\ifsinglechar){($copper\test)}{:} $nnn will expand $prmb(true)
+%$nnn$!$!$!now clever!
+% \catcode`\$stform[$blue]: \active \let$stform[$blue]:=\fi
+% \def($copper\test){($red\ifsinglechar)$stform[$blue]:}
+% \let:=\else
+% ($copper\test):$mprm(true)$mprm(false) $nnn will expand $prmb(true)
+% ($copper\test)\fi$mprm(true)$mprm(false) $nnn will expand $prmb(false)
+% ($copper\test)\else$mprm(true)$mprm(false) $nnn will expand $prmb(false)
+% \end{VerbLines}
+%
+% {\rmk \cs{ifsinglechar} is used in the definition of \cmdref{FE@ifchar}.}
+%
+% \cmditem-{ifOneChar}{ string }{ true }{ false }
+%
+% \csbf{ifOneChar} \FEII expands to \prm{true} if \textbfsf{\prmb{string} is a single character}.
+%
+% \textbfsf{\prmb{string} is detokenized} before the test (therefore, |\relax| for example does not contain a single \textsfsl{character}):§§
+% \begin{VerbLines}[commandchars=$\[\]]
+% [$red\ifOneChar]{A} $nnn will expand $prmb[true]
+% [$red\ifOneChar]{[$blue$textvisiblespace]A} $nnn will expand $prmb[false]
+% [$red\ifOneChar]{A[$blue$textvisiblespace]} $nnn will expand $prmb[false]
+% [$red\ifOneChar]{[$blue$textvisiblespace]} $nnn will expand $prmb[true] (even if there are many spaces !)
+% [$red\ifOneChar]{} $nnn will expand $prmb[false]
+% [$red\ifOneChar]{\relax} $nnn will expand $prmb[false] ($cs[relax] is detokenized)
+% [$vbmd$dg\let\ZERO=0]
+% [$red\ifOneChar]{\ZERO} $nnn will expand $prmb[false] ($cs[ZERO] is detokenized)
+% \end{VerbLines}
+%
+% {\rmk \cs{ifOneChar} is used in \cmdref{detokenizeChars} }
+%
+% \cmditem-{ifOneCharWithBlanks}{ string }{ true }{ false }
+%
+% \csbf{ifOneCharWithBlanks}\FEII switches to \prm{true} if and only if \prm{string} contains a single \textsfbf{character}
+% possibly with blank spaces before and/or after. It's an optimisation of:§
+% \qquad|\ExpandNext\ifOneChar{\expandnext\deblank{\detokenize{|\prm{string}|}}}|
+%
+% If \prm{string} contains \textbfsf{only spaces}, \cs{ifOneCharWithBlanks} expands \prmb{false}.
+%
+% \cmditem[iffirsttoken]@{iffirsttoken~\spot\tsptb iffirstchar}
+% \cmditem-{iffirsttoken}{ string1 }{ string2 }{ true }{ false }
+%
+% \csbf{iffirsttoken}\FEII compares the very first tokens of each \prm{string}. The
+% comparison is done using \csbf{ifx} and the macro is fully expandable. Neither \prm{string1} nor \prm{string2}
+% is expanded before comparison. Example:§
+% \qquad|\iffirsttoken \relax{\relax\textbf{hello world}}{begins with \relax}{begins with something else}|
+%
+% \qquad|\iffirsttoken|\mprm{}\mprm{whatever}¤expands\prmb{true} only if \prmb{whatever} is empty.
+%
+% \cmditem-{iffirstchar}{ string1 }{ string2 }{ true }{ false }
+%
+% \csbf{iffirstchar}\FEII compares the character codes of the \textbf{first} characters of each \prm{string}. The
+% comparison is \emph{catcode agnostic} and the macro is fully expandable. Neither \prm{string1} nor \prm{string2}
+% is expanded before comparison. Example:§
+% \qquad|\iffirstchar *{*hello*}{begins with a star}{begins with something else}|
+%
+% Alternatively, you may use the \cmdref{ifstrmatch} test.
+%
+% \qquad|\iffirstchar|\mprm{}\mprm{whatever}¤expands\prmb{true} only if \prmb{whatever} is empty.
+%
+% \ClearPage
+% \cmditem+{ifiscs}{ string }{ true }{ false }
+%
+% \csbf{ifiscs}\FEII will expand \prmb{true} only \textbfsf{if \prmb{string} is a single control word.} \prm{string}
+% may be anything, including \cs{if}-conditional, even not properly closed:§§
+% \begin{VerbLines}[commandchars=!()]
+% (!red\ifiscs){\MyMacro} !nnn will expand !prmb(true)
+% (!red\ifiscs){x} !nnn will expand !prmb(false) !textemdash even if x is active
+% (!red\ifiscs){\ifx AB C\else D\fi} !nnn will expand !prmb(false)
+% (!red\ifiscs){(!blue!textvisiblespace)\else} !nnn will expand !prmb(false)
+% (!red\ifiscs){\else(!blue!textvisiblespace)} !nnn will expand !prmb(true)
+% (!red\ifiscs){(!blue!textvisiblespace)} !nnn will expand !prmb(false)
+% (!red\ifiscs){\@sptoken} !nnn will expand !prmb(true)
+% (!red\ifiscs){} !nnn will expand !prmb(false)
+% (!dg!md\let\ALPHA=A)
+% (!red\ifiscs){\ALPHA} !nnn will expand !prmb(true)
+% \end{VerbLines}
+%
+% \cs{ifiscs} is an optimized form of: ``\cs{ifOneToken} AND NOT \cs{ifOneChar}''.
+%
+% {\rmk \cs{ifiscs} is used in the definition of the \cmdref=[DeclareCmdListParser]{command-list parsers}.}
+%
+% \cmditem{detokenizeChars}{ list of single tokens }
+%
+% \csbf{detokenizeChars}\FE will selectively detokenize the tokens in \prm{list of single tokens}. That means: single
+% characters (tested with \cmdref{ifOneChar}) are detokenized while control sequences are not detokenized:§§
+% \begin{VerbLines}[commandchars=!()]
+% \edef(!copper\result){(!red\detokenizeChars){!blue*+=!spview[!black]$@(!dg\relax\else);}}
+% (!copper\result): !chcat*(12)!chcat+(12)!chcat=(12)!chcat(!spview)(10)!chcat$(12)!chcat@(12)(!dg\relax\else)!chcat;(12)
+% \end{VerbLines}
+%
+% {\rmk \cs{detokenizeChars} is used in the normal form of \cmdref{futuredef}.}
+%
+% \cmditem{protectspace}{ code }
+%
+% \csbf{protectspace}\FEII will protect the spaces in \prm{code}, replacing spaces by a space surrounded by braces:§§
+% \setbox\helpbox\hbox{\texthl{\spview[\red]}} \setbox\helpboxx\hbox{\hl{\hbox{\{\spview[\red]\}}}}
+% \begin{VerbLines}[commandchars=$()]
+% \def($copper\test){abc$hpbox$hpbox$!$!$! def\else\relax\fi ghi$hpbox$hpbox$!$!$! j$hpbox}
+% \edef($dg\result){\unexpanded\expandafter\expandafter\expandafter{%
+% ($red\protectspace){($copper\test)}}}
+% \meaning($dg\result): macro:->abc$hpboxx$!$!$! def\else \relax \fi ghi$hpboxx$!$!$! j$hpboxx
+% \end{VerbLines}
+%
+% N.B.: there is no space after |\fi| in the definition of \cs[\copper]{test}...
+%
+% {\rmk \cs{protectspace} is used in \cmdref{detokenizeChars}.§
+% \cs{protectspace} is an example of a \textbf{recursive macro which is 2-purely expandable. }}
+%
+% \end{ltxsyntax}
+%
+% \Section{Characters and Strings}
+%
+% \begin{ltxsyntax}
+%
+% \cmditem+{ifempty}{ string }{ true }{ false }
+%
+% \csbf{ifempty}\FEII is similar to |\ifblank| but it test if a string is really empty
+% (it shall not contain any character nor spaces). To test if the replacement
+% text of a macro is empty, one may use |\ifempty| in conjunction with \cmdref{expandnext}:
+%
+% \begin{tabbing}
+% \quad\=|\expandnext\ifempty{\macro}| \prm{true}\prm{false}
+% \end{tabbing}
+%
+% |\ifempty| is based on |\detokenize| and accept anything in its argument.
+%
+% {\rmk This is NOT: |\expandafter\ifx\expandafter\relax\detokenize{\#1}\relax| !}
+%
+% \cmditem{xifempty}{ string or cs-token }{ true }{ false }
+%
+% |\xifempty|\pdfFE is similar to |\ifempty| but the argument is expanded during comparison.
+%
+% \begin{tabbing}
+% \quad\=|\def\x{\@empty}\def\y{}| \\
+% \>|\xifempty{\x\y}| \prm{true}\prm{false}¤¤ will expand \prm{true}
+% \end{tabbing}
+%
+% {\rmk If pdf\TeX{} is in use, the macro is based on the \cs{pdfstrcmp} primitive.}
+%
+% \cmditem{ifnotempty}{ string }{ true }{ false }
+%
+% \csbf{ifnotempty}\FEII reverses the test of |\ifempty|.
+%
+%
+% \cmditem{xifblank}{ string }{ true }{ false }
+%
+% |\xifblank|\notFE\\ is similar to |\ifblank| except that the \prm{string} is first expanded
+% with \cs{protected@edef}.
+%
+% \cmditem{ifnotblank}{ string }{ true }{ false }
+%
+% \csbf{ifnotblank} \FEII reverses the test of |\ifblank|.
+%
+% {\rmk |\ifnotblank| is a foundamental of purely expandability. It is extensively used in \thispackage
+% but in an optimized form: \cmdref[impl:ettl@nbk]{ettl@nbk}.}
+%
+%
+% \cmditem+{deblank}{ string }
+%
+% |\deblank|\FEII removes all leading and trailing blank spaces from its argument.\medbreak
+%
+% An application is for the normalisation of comma separated lists:§§
+% \begin{VerbLines}[commandchars=!()]
+% \csvloop!stform*[(!red\deblank)]{ item1 , item2 , item3
+% , item4 , item5 ,item6 ,
+% item7 , item8}%
+% !nnn will normalize the list:§
+% {item1,item2,item3,item4,item5,item6,item7,item8}
+% \end{VerbLines}
+%
+% This construction is purely expandable:§
+% \qquad |\edef\result{|\cmdref{csvloop}|[|\cs[\red]{deblank}|]{|...|}}|§
+% will normalize the list and assign the result to the replacement text of \cs{result}.
+%
+% For more on normalisation, refer to the \Xpackage{kvsetkeys}\footnote{\xpackage{kvsetkeys}-normalisation also
+% include a replacement of \CH{,} and \CH{=} to ensure that their category code are 12.} package.
+%
+%
+% \cmditem{ifstrcmp}{ string1 }{ string2 }{ true }{ false }
+%
+% \csbf{ifstrcmp}\pdfFE is based on the |\pdfstrcmp| primitive (or the XeTeX-|\strcmp|) if available. Otherwise,
+% |\ifstrcmp| is |\let| to \xpackage{etoolbox}-\cs{ifstrequal}.
+%
+% Neither \prm{string1} nor \prm{string2} is expanded during comparison. The comparison is
+% \emph{catcode agnostic} (use of |\detokenize |).
+%
+% \cmditem{xifstrequal}{ string1 }{ string2 }{ true }{ false }
+%
+% |\xifstrequal|\notFE\ is the same as \xpackage{etoolbox}-|\ifstrequal| apart that each parameter string is expanded
+% (with |\protected@edef|) before comparison.
+%
+% \cmditem{xifstrcmp}{ string1 }{ string2 }{ true }{ false }
+%
+% |\xifstrcmp|\pdfFE is the \LaTeX{} form of |\pdfstrcmp| primitive. If this primitive is not available,
+% |\xifstrcmp| is |\let| to |\xifstrequal|.
+%
+% \prm{string1} and \prm{string2} are expanded during comparison.
+%
+% \cmditem[ifcharupper]@{ifcharupper\tsptb ifcharlower}
+% \cmditem-{ifcharupper}{ single char }{ true }{ false }
+% \cmditem-{ifcharlower}{ single char }{ true }{ false } \FEII*
+%
+% \csbf{ifcharupper}\FEII compares with |\ifnum| the character code of \prm{single char} with its |\uccode|.
+%
+% \csbf{ifcharlower} compares with |\ifnum| the character code of \prm{single char} with its |\lccode|.
+%
+% \cmditem{ifuppercase}{ string }{ true }{ false }
+% \cmditem-{iflowercase} {string }{ true }{ false }
+%
+% \csbf{ifuppercase}\notFE\ compares the \prm{string} with |\uppercase{|\prm{string}|}|.
+%
+% \csbf{iflowercase} compares the \prm{string} with |\lowercase{|\prm{string}|}|.
+%
+% The commands are robust.
+%
+% \cmditem{ifstrmatch}{ pattern }{ string }{ true }{ false }
+%
+% \csbf{ifstrmatch}\pdfFE is based on the |\pdfmatch| primitive that implements POSIX-regex.
+%
+% You can test the last character of a string in a purely expandable way by:
+% \begin{tabbing}
+% \quad\=\cs{ifstrmatch}\{[\textasteriskcentered]\$\}\{\prm{string}\}
+% \end{tabbing}
+% for example to test \CH{\textasteriskcentered} at the end of a string.
+%
+% \ClearPage
+% \cmditem[ifstrdigit]@{ifstrmatch~\spot\tsptb ifstrnum}
+% \cmditem-{ifstrdigit}{ string }{ true }{ false }
+%
+% \csbf{ifstrdigit}\FEII expands to \prm{true} if \prm{string} is a single digit.
+%
+% A \emph{single digit} is $0,1,2,3,4,5,6,7,8$ or $9$ without spaces around, no matter of the category code.
+%
+% \ClearPage
+% \cmditem-{ifstrnum}{ string }{ true }{ false }
+%
+% \csbf{ifstrnum}\FEII expands to \prm{true} if \prm{string} is a \textbfsf{number in the sense of \eTeX}, that means:
+%
+% \qquad|\number|\prm{string}\qquad will be the same as:\qquad|\deblank|\mprm{string}
+%
+% under the standard catcode regime, if \prm{string} is a positive integer.
+%
+% in other words:§§
+% \begin{VerbLines}[commandchars=!()]
+% \edef(!copper\resultA){(!red\number)(!nnn!prm(string))}
+% \edef(!dg\resultB){(!red\deblank)(!nnn!mprm(string))}
+% \ifx(!copper\resultA)(!dg\resultB) !nnn is(!nbf true) if !mprm(string) is a positive integer
+% \end{VerbLines}
+%
+% \prm{string} must be of the form:¤{\Large{\blue\textvisiblespace--\textvisiblespace--\textvisiblespace}{\red$\mathbf{\star\star\star}$}{\blue\textvisiblespace}}\par
+% \hfil where {\blue blue} is optional (one ore more spaces and/or minus signs)\hfil§
+% \hfil {\red$\mathbf{\star\star\star}$} denotes 1 or more digit(s) without spaces around\hfil§
+% for \cs{ifstrnum} to expand to \prm{true}.
+%
+% To tell all the truth, \cs{ifstrnum} expands \prm{true} even if digits have a category code$\neq 12$ whereas
+% |\number| throws an error or stops.
+% But if numbers and minus signs are of category 12 (more than recommended after all...)
+% {\sfbf\csbf{ifstrnum} is a purely expandable test to check if it is possible to expand
+% \csbf{number} {\md(or \cs{romannumeral})} onto \prmb{string}} (but \cs{ifstrnum} does not expand \prm{string}.)
+%
+% \bigbreak
+%
+% \ClearPage
+% \cmditem+{DeclareStringFilter}[\cs{global}]{ command-name }{ stringA }
+% \newcommand\myitem[1]{\item[\hss{\stform[\rred\large]{#1}}\hss]} ^^A\newcommand*\interitem{\item[]\hskip-\leftmargin}
+%
+% With \csbf{DeclareStringFilter}\notFE, you will define \textbf{a purely expandable command} designed to test
+% if a string:
+% \begin{itemize}[labelsep=2em,leftmargin=5em]
+% \myitem= is is \textbfsf{equal} to a \textsl{given} string \prm{stringA} (with possibly spaces before and after)
+% \myitem{==} is \textbfsf{strictly equal} to a \textsl{given} string \prm{stringA} (no spaces allowed)
+% \myitem< \textbfsf{begins with} \prm{stringA} (possibly with leading spaces)
+% \myitem{<=} \textbfsf{strictly begins with} \prm{stringA} (no leading spaces allowed)
+% \myitem> \textbfsf{ends with} \prm{stringA} (possibly with trailing spaces)
+% \myitem{>=} \textbfsf{strictly ends with} \prm{stringA} (no trailing spaces allowed)
+% \myitem? \textbfsf{contains} \prm{stringA}, and optionally how many times
+% \interitem and also your \textitbf{\sffamily string-filter} will be able to
+% \myitem\textendash \textbfsf{remove} \prm{stringA} from any string $0$, $1$ or more times\\
+% ¤¤(maximum = |\ettl@intmax|$ = 2^{13}-1 = $\numprint{2147483647})
+% \myitem+ \textbfsf{replace} \prm{stringA} by any other string $0$, $1$ or more times
+% \myitem! \textbfsf{count} the number of occurences of \prm{stringA} in any string
+% \end{itemize}
+%
+% {\hfill\mycolorbox{\bf Equality is \CSbf{catcode} dependent.}\hfill}
+%
+% You may also check that \prm{stringA} may be a blank space (but as for now, you cannot
+% replace blank spaces at the end of the string...).
+% \ClearPage
+% \newcommand\¤[1][]{\textcolor{blue}{\bfseries{\vbbf\textvisiblespace}#1}}
+%
+% Let's see how this works (\¤\ is zero or more spaces):§§\enlargethispage{5\baselineskip}
+% \def\YES{\textcolor{blue}{\bfseries YES}} \newcommand\bigskipneg{\vskip-8pt}
+% \def\YYESS{\¤[YES]\¤}
+% \def\YYES{\¤[YES]}
+% \def\YESS{\textcolor{blue}{\bfseries YES}\¤}
+% \let\verbatimfont\tt
+% \begin{VerbLines}[commandchars=$(),fontseries=b]
+% ($red\DeclareStringFilter)($copper\CompareYES){$YES} ($nnn defines $CSbf(CompareYES))
+% ($nnn$csbf(CompareYES) is the ($itbf$sffamily string-filter) for the string "$YES" $quad$smex $prm(stringA))
+%
+% ($copper\CompareYES) $mprm(string)$mprm(true)$mprm(false)($nnn expands $prm(true) if $prm(string) $nbf is "$YYESS")
+% ($copper\CompareYES)($rred$large=) $mprm(string)$mprm(true)$mprm(false)($nnn is the same)
+% ($copper\CompareYES)($rred$large=.)$mprm(string)$mprm(true)$mprm(false)($nnn is also the same)
+% ($copper\CompareYES)($rred$large==)$mprm(string)$mprm(true)$mprm(false)($nnn expands $prm(true) if $prm(string)$nbf is "$YES")
+%
+% ($copper\CompareYES)($rred$large<) $mprm(string)$mprm(true)$mprm(false)($nnn expands $prm(true) if $prm(string)$nbf begins with "$YYES")
+% ($copper\CompareYES)($rred$large<=)$mprm(string)$mprm(true)$mprm(false)($nnn expands $prm(true) if $prm(string)$nbf begins with "$YES")
+%
+% ($copper\CompareYES)($rred$large>) $mprm(string)$mprm(true)$mprm(false)($nnn expands $prm(true) if $prm(string)$nbf ends with "$YESS")
+% ($copper\CompareYES)($rred$large>=)$mprm(string)$mprm(true)$mprm(false)($nnn expands $prm(true) if $prm(string)$nbf ends with "$YES")
+%
+% ($copper\CompareYES)($rred$large?) $mprm(string)$mprm(true)$mprm(false)($nnn expands $prm(true) if $prm(string)$nbf contains "$YES")
+% ($copper\CompareYES)($rred$large?[($itbf$!$!$! n)])$mprm(string)$mprm(true)$mprm(false)$nnn expands $prm(true) if $prm(string)
+% $hfill$nbf contains "$YES" more than($itbf n) times
+%
+% ($copper\CompareYES)($rred$large-) $mprm(string) $nbf removes all occurences $nnn of "$YES" in $prm(string)
+% ($copper\CompareYES)($rred$large-[($itbf$!$!$! n)])$mprm(string) $nbf removes at most($itbf n) occurences $nnn of "$YES"
+%
+% ($copper\CompareYES)($rred$large+) $mprm(string)$mprm(stringB) $nbf replaces all occurences
+% $hfill$nbf of "$YES" by $prm(stringB) in $prm(string)
+% ($copper\CompareYES)($rred$large+[($itbf$!$!$! n)])$mprm(string)$mprm(stringB) $nbf replaces at most($it n) occurences
+% $hfill$nbf of "$YES" by $prm(stringB) in $prm(string)
+% ($nnn And finally:)
+% ($copper\CompareYES)($rred$large!){$prm(string)} $nnn expands to($nbf the number of times "$YES") can be found in $prm(string)
+% \end{VerbLines}
+%
+% \let\verbatimfont\verbfont
+% A problem may arise if the \prm{string} to compare is the string \CH{\vbbf\blue=}, because purely expandable
+% tests for modifiers don't make difference between \CH{=} and \CH{\{=\}}. To avoid this problem,
+% you may say {\vbbf\red=.} or {\vbbf\red>.} or {\vbbf\red>.} instead of {\vbbf\red=}, {\vbbf\red>} and {\vbbf\red<}.
+%
+% All the same, you may say {\vbbf\red?.}, {\vbbf\red+.} and {\vbbf\red-.} to avoid problems if the \prm{string} is \CH{\stform[\blue][}.^^A]
+%
+% {\rmk \cs{CompareYES} and each of its form are purely expandable thank to \cmdref{FE@modifiers}.}
+%
+% You should not test a \prm{string} which contains the following sequence:§
+% \hfill\colorbox{ly}{$/__8$E$__{11}$n$__{11}$d$__{11}\S__7$S$__{11}$t$__{11}$r$__{11}$i$__{11}$n$__{11}$g$__{11}/__8$}\hfill\kern0pt\par
+%
+% {\rmk nor a string which contains \CH{\chcat/8} because \chcat/8 has a special meaning for \thispackage-\cmdref*{ettl@nbk}.}
+%
+% \end{ltxsyntax}
+%
+% \ClearPage*
+%
+% \Section{Fully expandable macros with options and modifiers}
+%
+% With \cs{ifblank} and \cs{ifempty} which are purely expandable macros, it becomes possible to write fully expandable
+% macros with an option, \textbf{provided that this macro has at least one non-optional argument},
+% as far as we don't use |\futurelet| nor any assignment.
+%
+% \begin{ltxsyntax}
+%
+% \cmditem{FE@testopt}{\#1}{ commands }{ default option }
+%
+% \csbf{FE@testopt}\FE mimics the behaviour of |\@testopt| but is Fully Expandable (\sty{FE}) and can be used as follow:§§
+% \begin{VerbLines}[commandchars=!()]
+% \def(!copper\MacroWithOption)!#1{(!red\FE@testopt){!#1}\MacroHasOption{default}}
+% \end{VerbLines}
+%
+% \textbfsf{Limitation:} \cs{FE@testopt} will look for an option if \#1 is \CH{\chcat{[}{12}} (without spaces around). Therefore:§
+% \qquad|\MacroWithOption{|{\stform[\blue][}|}{|...|}|¤ will most probably lead to an error... because \cs{FE@testopt} is looking
+% for an option. This is the price, for purely expandability (all the same for \cmdref{FE@ifstar}, \cmdref{FE@ifchar}
+% and \cmdref{FE@modifiers}).
+%
+% Just like \cs{@testopt}, \cs{FE@testopt} is sensitive to the category code of \CH{\chcat\textasteriskcentered{12}} which must be \textvb{other}.
+%
+% {\rmk |\FE@testopt| is used in the definition of \cmdref{DeclareStringFilter}, \cmdref{avoidvoid}, \cmdref{ettl@supergobble}
+% and \cmdref{csvtolist}.}
+%
+% \cmditem{FE@ifstar}{\#1}{ star-commands }{ non-star commands }
+%
+% Similarly, it\FE becomes possible to mimic the behaviour of |\@ifstar| but in a fully expandable(\sty{FE}) way.
+% \csbf{FE@ifstar} can be used as follow:§§
+% \begin{VerbLines}[commandchars=!()]
+% \def(!copper\StarOrNotCommand)!#1{(!red\FE@ifstar){!#1}
+% {\StarredCommand}
+% {\NotStarredCommand}}
+% \end{VerbLines}
+%
+% Just like \cs{@ifstar}, \cs{FE@ifstar} is sensitive to the category code of \stform* which must be \textvb{other}.
+%
+% {\rmk |\FE@ifstar| is used in the definitions of \cmdref{csvtolist}, \cmdref{listtocsv} and \cmdref{tokstolist}.}
+%
+% \cmditem{FE@ifchar}{ Variant Character }{\#1}{ special-commands }{ normal-commands }
+%
+% As a\FE generalisation of \cs{FE@ifstar} \thispackage provides \csbf{FE@ifchar} for use with other variants than the \stform*-form.
+%
+% For example, to define a \CH{\stform+} variant:§§
+% \begin{VerbLines}[commandchars=!()]
+% \def(!copper\SpecialFormMacro)!#1{(!red\FE@ifchar)(!blue!ttbf+){!#1}
+% {\SpecialFormMacro}
+% {\NormalFormMacro}
+% \end{VerbLines}
+%
+% Like \cmdref{@ifchar} but \textsfsl{\bfseries unlike} \cs{@ifstar} and \cs{FE@ifstar}, \cs{@testopt} and \cs{FE@testopt}
+% \csbf{FE@ifchar} is NOT sensitive to the category code of the \prm{Variant Character} (the \cmdref={character-test} is used).
+%
+% \textsfsl{Really, \csbf{FE@ifchar} is based on \cmdref{ifsinglechar} therefore the ``caracter'' to test may be any token,
+% and you may define a purely expandable macro with a \CH{\cs{relax}} form, a \CH{\cs{ignorespaces}} form and a
+% \CH{\cs{afterassignment}} form.} But may be this is useless...
+%
+%
+% \ClearPage*
+% \cmditem+{FE@modifiers}{ Allowed Modifiers }{\#1}{ 1st case }{ 2nd case }{...}{ Normal case }
+%
+% \csbf{FE@modifiers}\FE is a generalization of \cmdref{FE@ifchar} to allow different modifiers for a single macro.
+% The first argument is the \prm{Allowed Modifiers} for this macro.
+%
+% For example, if you want to define a \textbf{purely expandable} macro with a \stform[\blue]* \textbfsf{star} form, a
+% \stform[\blue]+ \textbfsf{plus} form and a \stform[\blue]{--} \textbfsf{minus} form you may say:§§
+% \begin{VerbLines}[commandchars=&()]
+% \def(&copper\MySuperMacro) &#1{(&red\FE@modifiers{(&blue * + - )}){&#1}
+% {(&mdseries\MySuper(&blue&!Starred)Macro)} (&nnn&% first position)
+% {(&mdseries\MySuper(&blue&!Plus)Macro)} (&nnn&% second position)
+% {(&mdseries\MySuper(&blue&!Minus)Macro)} (&nnn&% third position)
+% {(&mdseries\MySuperMacro(&blue&!Without)Modifier)}} (&nnn&% next to last position)
+% \end{VerbLines}
+% Then when called by the user, {\copper|\MySuperMacro|} will switch to the sub-macro corresponding
+% to the modifier specified (purely expandable macro with different modalities).
+% \iffalse
+% If you don't care on pure-expandability, you may define macros with modifiers yet more easily with
+% the \cmdref={macromodifiers} environment.
+% \fi
+%
+% \cs{FE@modifiers} works as follow:\par\nobreak
+% \begin{enumerate}[label=\arabic*)~,beginpenalty=10000]
+% \item it checks if \#1 is a single character (\cmdref{ifOneToken} does the job)
+% \item then it tries to find it in the list of \prm{Allowed Modifiers} (this is a \cmdref={list of single tokens})
+% \item if found, the index of the modifier in the list is known, as well as the length of the list. Then,
+% \cmdref{ettl@supergobble} expands the chosen one.
+% \end{enumerate}
+%
+% \cs{FE@modifiers} uses the \cmdref={character-test}. Therefore, single \textbfsf{\slshape character tokens} are found
+% in the list of \prm{Allowed Modifiers} even if their category code don't match.
+%
+% {\rmk \cs{FE@modifiers} is used in the definition of the string-filters defined with \cmdref{DeclareStringFilter}.§
+% An intesting example of use of \cs{FE@modifiers} is given in the implementation of \cmdref*{ettl@lst@modif}.}
+%
+% \cmditem{ettl@supergobble}[code]{\blue$\mathbf n$}{\blue $\mathbf N$}{tok$_1$}|...|{tok$_n$}{\blue\bfseries TOK$_{\mathbf{n+1}}$}{tok$_{n+2}$}|...|{tok$_{\blue\mathbf N}$}
+%
+% \csbf{ettl@supergobble}\{\PRM[\blue]{$\mathbf n$}\}\{\PRM[\blue]{$\mathbf N$}\}\FE will:
+% \begin{enumerate}[label=\roman*)~]
+% \item gobble the first \PRM[\blue]{$\mathbf n$} tokens (or groups of tokens) it founds just after
+% \item keep the \PRM[\blue]{$\mathbf{n+1}$} token
+% \item gobble the last tokens \PRM[\blue]{$\mathbf{n+2}$} to \PRM[\blue]{$\mathbf{N}$}
+% \item then and after all, expand to \PRM[\blue\bfseries]{TOK$_{\mathbf{n+1}}$}
+% \end{enumerate}
+%
+% In other words, the list contains \PRM[\blue]{$\mathbf{N}$} tokens, \csbf{ettl@supergobble} expands the \PRM[\blue]{$\mathbf{n+1}$}
+% and discards the rest.
+%
+% Now if \PRM[\blue]{$\mathbf{n}$}$=$\PRM[\blue]{$\mathbf{N}$}, \csbf{ettl@supergobble}
+% gobbles the \PRM[\blue]{$\mathbf{N}$} tokens (including the last).
+%
+% And if \PRM[\blue]{$\mathbf{n}$}$>$\PRM[\blue]{$\mathbf{N}$} or if \PRM[\blue]{$\mathbf{n}$}$<0$,
+% \csbf{ettl@supergobble} expands to \PRM[\blue]{\bfseries TOK$_\mathbf{N}$} (the last).
+%
+% Finally, if the optional parameter \oprm{code} is specified, it will be appended to the list after \prm{tok$_{N}$} (but not in the
+% special case where $n$=$N$...).
+%
+% {\rmk \cs{ettl@supergobble} has been designed for and is used in \cmdref{FE@modifiers}.§
+% If you're interested in what \cs{ettl@supergobble} does when \PRM[\blue]{$\mathbf N$}$\leq 0$: it does nothing!}
+%
+% \end{ltxsyntax}
+%
+% \ClearPage*
+%
+% \Section[{More options with \texorpdfstring{\cs[\sfbf]{futuredef}}{\cs{futuredef}}}]{More options with \csbf{future{\spot def}} : vectorized \csbf{future{\blue let}}: }
+%
+% \begin{ltxsyntax}
+%
+% \cmditem+{@ifchar}{ single token }{ true }{ false }
+%
+% \csbf{@ifchar}\notFE\ does the same as \LaTeX'\cs{@ifstar} but for any character (or \textsfsl{modifier}). Whereas
+% \cs{@ifstar}-test is sensitive to the category code of the star (the \textsfsl{character
+% \CH{\chcat[\blue\vbbf]\textasteriskcentered{12}}} -- that means that the category code of \stform[\blue]* must be $12$
+% as defined in \LaTeX's kernel), \csbf{@ifchar} is based on the \cmdref={character-test}
+% and does not check the equality of category code for single \textbf{characters}.
+%
+% \cs{@ifchar} is NOT purely expandable. It relies on |\futurelet| and on the \cmdref={character-test}.
+% The syntax is the same as for \cs{@ifstar} with the specification of the (character) token to test:§§
+% \begin{VerbLines}[commandchars=!()]
+% \newcommand(!copper\SpecialMacro){(!red\@ifchar)(!blue+)%
+% {\let\modifier=+\GeneralMacro}
+% {\let\modifier=\relax\GeneralMacro}}
+% \end{VerbLines}
+%
+% {\rmk Unless \cs{@ifstar}, \cs{@ifchar} is a |\long| macro...}
+%
+% \cmditem+{@char@testopt}{ code }{ single token }{ default option }{ single token }
+%
+% \csbf{@char@testopt}\notFE is a generalization of \LaTeX's\cs{@testopt} that may be used as follow:§§
+% \begin{VerbLines}[commandchars=!$£]
+% \newcommand$!copper\SpecialMacro£{$!red\@char@testopt£\GeneralMacro({default})}
+% $!nnn with£\GeneralMacro$!nnn a macro accepting optional parenthesis:£
+% \def\GeneralMacro(#1){...}
+% $!nbf or:£
+% \newcommand$!copper\SpecialMacro£{$!red\@char@testopt£\GeneralMacro<{default}>}
+% $!nnn with£\GeneralMacro$!nnn a macro accepting optional brackets:£
+% \def\GeneralMacro<#1>{...}
+% \end{VerbLines}
+%
+% {\rmk NB: \cs{@char@testopt} uses \cmdref{ettl@ifnextchar} and therefore, the category code of single
+% \textbf{characters} is not taken into account.}
+%
+% ^^A \cmditem+{@ifnextchardigit}{ true }{ false }
+% ^^A
+% ^^A \cs{@ifnextchardigit}\notFE\ expands \meta{true} only if the next character is a digit (\ie 0, 1, 2, 3, 4, 5, 6, 7, 8 or 9).
+%
+% \cmditem{ettl@ifnextchar}{ single token }{ true }{ false }
+%
+% \csbf{ettl@ifnextchar}\notFE\ is the engine for \csbf{@ifchar}. It is based on \cs{futurelet} and on the \cmdref={character-test}:§§
+% \begin{VerbLines}[commandchars=$()]
+% $dg\begingroup \catcode`\$stform[$blue]! \active \let$stform[$blue]!=\else
+% $dg\gdef ($copper\test) {($red\ettl@ifnextchar) $stform[$blue]!{true}{false\@gobble}}
+% $dg\endgroup
+% \catcode`\$stform[$dc]!\active \let$stform[$dc]!=\ifodd
+% ($copper\test)$stform[$dc]! $nnn will expand $prmb(true)
+% ($copper\test)\ifodd $nnn will expand $prmb(false)
+% ($copper\test)\else $nnn will expand $prmb(false)
+% \end{VerbLines}
+% \bigbreak
+%
+% \thispackage defines a vectorized version of \cs{futurelet}. The idea is to say:
+%
+% \quad|\futuredef[|\prm{list of allowed tokens}|]\macro{|\prm{commands to execute next}|}|
+%
+% Then \cs{futuredef} is a kind of simple scanner for tokens. It can be used to define an \textbf{\textit{undelimited macro}}
+% \ie a macro that has no delimiter but whose content of arguments is restricted.
+%
+%
+% \cmditem+{futuredef}[ list of allowed tokens ]{ \cs{macro} }{ commands to expand after }
+% \cmditem-{futuredef\stform*}[ list of allowed tokens ]{ \cs{macro} }{ commands to expand after }
+%
+% \csbf{future\spot def}\notFE\ will read the following token with \csbf{future\blue let}. If that token is in the
+% \prm{list of allowed tokens}, then it will append it to \cs{macro} and continue, scanning the tokens one after another.
+% \end{ltxsyntax}
+%
+% Until it founds a token which is not in the \prm{list of allowed tokens}. Then it stops reading
+% and executes the \prm{commands to expand after}. Those commands may use the \cs{macro}
+% just defined for analyse or whatever the user want.
+%
+% The space token must be \textbfsf{explicitly specified} in the \prm{list of allowed tokens}:
+% otherwise \cs{futuredef} stops at a space (and executes the \prm{commands to expand after}).
+%
+% \textbfsf{A token is in the \prmb{list of allowed tokens} \textcolor{blue}{if it can be found in this list using
+% the \cmdref={character-test}}.} This means that if \cs[\blue]{relax} is in the \prmb{list of allowed tokens}, then it will
+% be appended to \cs{macro} (if encountered) and if \CH{\chcat\${3}} is in the \prmb{list of allowed tokens}, any
+% \CH{\stform[\blue]\$} character will be appended to \cs{macro} (if encountered) no matter of its category code. If you really
+% absolutely need the \cs{ifx}-test, you shall use \cmdref[futuredef=]{futuredef\stform=}\footnote{this may be the case if,
+% for some reason, you have detokenized the \prm{list of allowed tokens} before, and want to skip the expansion of \cs{detokenizeChars}
+% which occurs at the beginning of the normal form of \cs{futuredef}...}.
+%
+% \textbfsf{If the \prmb{list of allowed tokens} is not specified,} \cs{futuredef} will read all tokens until the next
+% \textsfsl{begin-group} or \textsfsl{end-group} token.
+%
+% \cs{futuredef} may be used instead of \cs{FE@modifiers} for (non purely expandable) macros with multiple modifiers.
+% (The modifiers of the \cs{newkeycommand} macro in the \Xpackage{keycommand} package are scanned with this feature.)
+% As far as it is based on \cs{futurelet}, the limitation of \cs{FE@modifiers} (\ie |{|\stform*|}| is the same as \stform*
+% without the braces) is not applicable to \cs{futuredef}.
+%
+% \textbf{Limitation: } as far as \cs{macro} has to be correctly defined (it's replacement text must be balanced
+% in begin-group\slash end-group delimiters) \textbfsf{it is not allowed to have a character of category code $\mathbf1$ or $\mathbf2$}
+% (or a token having been |\let| to such a character)\textbfsf{ in the } \prmb{list of allowed tokens}:
+% \cs{futuredef} will stop scanning the next tokens if it encounters a begin-group or an end-group character.
+%
+% The \textbfsf{star-form} of \cs{futuredef} is more dangerous: \csbf{futuredef\stform*} captures the tokens as \cs{futuredef} does,
+% storing them into \cs{macro} as long as they are in the \prm{list of allowed tokens}. But if the next token is not in the
+% list, \cs{futuredef\stform*} does not stop at first stage but expands this very token and starts again.
+% \ClearPage
+%
+% Example:§§
+% \begin{VerbLines}[commandchars=!()]
+% \def\test{TeX\relax{*}}
+% (!red\futuredef)(!blue[TeX\relax])(!copper\macro){"\meaning\macro"}eTeX\test.
+% !hfill "macro:->eTeX" (!nnn each token is allowed until !cs(test))
+% (!red\futuredef!stform*)(!blue[TeX\relax])(!copper\macro){"\meaning\macro"}eTeX\test.
+% !hfill "macro:->eTeXTeX\relax " (!nnn!cs(test) is expanded and)
+% !hfill(!nnn futuredef stops at begin-group character)
+%\end{VerbLines}
+%
+% \medskip
+% As an application, it can be used to define an easy interface for |\hdashline| (the dashed lines in tabulars and arrays
+% provided by the \xpackage{arydshln} package): modifying \cmd{hline} in order to give sense to the following:
+% \begin{tabbing}
+% \qquad\=|\hline..|\qquad\=|\hline--|\qquad\=|\hline==|\qquad\= |\hline.-|\qquad\=|\hline.-.|\ \= etc.
+% \end{tabbing}
+%
+% After having collected the allowed tokens with:§
+% \csbf{futuredef}\textvbbf{[.-=]}\csbf{nexttokens}\{\prm{commands next}\} \quad it is possible to
+% test the pattern given using \cs{pdfstrcmp} or \cs{ifstrequal} (or even a \cmdref[DeclareStringFilter]{string-filter})
+% and, for example, the \CSbf{switch} construction of the \xpackage{boolexpr} package:
+% \begin{VerbLines}[fontseries=m]
+% \switch[\pdfstrcmp{\nexttokens}]%
+% \case{{..}}\hdashline[parameters]%
+% \case{{--}}\hdashline[parameters]%
+% \case{{==}}\hdashline[parameters]%
+% \case{{.-.}}\hdashline[parameters]%
+% \otherwise \original@hline%
+% \endswitch
+% \end{VerbLines}
+%
+% \CSbf{switch} is purely expandable. See \Xpackage{boolexpr} for more information on \cs{switch}.
+%
+% \begin{ltxsyntax}
+% \cmditem[starredfuturedef]{futuredef\stform=}[ list of allowed tokens ]{ \cs{macro} }{ commands to expand after }
+% \cmditem-{futuredef\stform*\stform=}[ list of allowed tokens ]{ \cs{macro} }{ commands to expand after }
+%
+% The \CH{\stform=} form\notFE\ of \cs{futuredef} is the same as \cs{futuredef} but the checking of single characters
+% is sensitive to their category code. If a control sequence is in the \prm{list of allowed tokens} it is appended to \cs{macro}
+% (if encountered) just like the normal \cs{futuredef} does. But if it is a single character token, then it is appended to \cs{macro}
+% only if the same character with the same ccategory code is found in the \prm{list of allowed tokens}: otherwise, \cs{futuredef}
+% stops reading and executes the \prm{commands to expand after}.
+% \end{ltxsyntax}
+%
+% In general, we are not willing this behaviour and the \stform= form of \cs{futuredef} would probably never be used, unless you know
+% that the \prm{list of allowed tokens} is already detokenized...
+% Anyway, it was not difficult at all to \cmdref=[impl:futuredef=]{implement}.
+%
+% {\rmk You may use indifferently \cs{futuredef\stform*\stform=} or \cs{futuredef\stform=\stform*}.}
+%
+% \ClearPage*
+% \Section{Define control sequences through groups}
+%
+% \begin{ltxsyntax}
+%
+% \cmditem[AfterGroup]@{AfterGroup\tsptb AfterGroup\stform*}
+% \cmditem-{AfterGroup}{ code }
+% \cmditem-{AfterGroup\stform*}{ code }
+%
+% The \cs[\red]{aftergroup}\notFE\ primitive does not allow arbitrary code: only a single token may be placed after \cs{aftergroup}.
+% \csbf{AfterGroup} allows arbitrary \prm{code} to be expanded after \cs{endgroup} or an end-group character.
+%
+% The \stform* star form of \cs{AfterGroup} does the same, but expands its argument with |\edef|:§§
+% \begin{VerbLines}[commandchars=!()]
+%!md \newcommand(!copper\macro)[1]{\textbf{Just to see...!#1}}
+% (!dg\begingroup)
+%!md \newcommand(!copper\othermacro)[1]{\textbf{will we see...!#1}}
+% (!red\AfterGroup)!md{(!copper\macro){if it works}}
+% (!red\AfterGroup*)!md{\expandonce{(!copper\othermacro){if it works}}}
+% (!dg\endgroup)
+% (!nnn and here) (!md(!copper\macro){if it works}) (!nnn will be executed)
+% (!nnn and here) (!md\textbf{will we see...if it works}) (!nnn will be executed)
+% \end{VerbLines}
+%
+% \cmditem{AfterAssignment}{ code }
+%
+% In the same order of idea,\notFE\ \csbf{AfterAssignment} allows arbitrary \prm{code} to be expanded \cs{afterassignment}.
+%
+% \cmditem+{aftergroup@def}{ command }
+%
+% When leaving\notFE\ a group with the end-group character \CH{\stform[\dg]\}} or the execution of \csbf[\dg]{endgroup}
+% the meaning of the control sequences that where locally defined inside the group are restored to
+% what they were before.
+%
+% The idea of \cs{aftergroup@def} is to keep a control sequence though \csbf[\dg]{endgroup} or \CH{\stform[\dg]\}}.
+% This is done by redefining it after the group. \cs{aftergroup@def} is based on \Xpackage[oberdiek/letltxmacro]{letltxmacro} and
+% on \cmdref{AfterGroup} just defined. Therefore, \cs{aftergroup@def} works with commands with optional arguments declared
+% with \LaTeX's \cs{newcommand}, with robust commands from \xpackage{etoolbox}-\cs{newrobustcmd} and
+% with \LaTeX's robust commands (\cs{DeclareRobustCommand}).
+%
+% \begin{VerbLines}[commandchars=!()]
+% { (!dg\newcommand)(!copper\test)[2][default]{ !#1 and !#2 }
+% (!red\aftergroup@def)(!copper\test)
+% }
+% (!copper\test)[option]{mandatory} (!nnn is defined outside the group - but NOT globally)
+% \end{VerbLines}
+%
+%
+% \end{ltxsyntax}
+%
+% \ClearPage*
+% \Section{Lists management}
+%
+% \Subsection{The natural loop}
+%
+% \begin{ltxsyntax}
+% \cmditem{naturalloop}[auxiliary commands]{ number of times }{ argument }
+%
+% {\bfseries The \csbf{naturalloop}\FE macro applies the \prmb{auxiliary commands} exactly $n$ times onto the
+% \prmb{argument},} \ie:§
+% \begin{framed}
+% \begin{tabbing}
+% ¤¤\hskip2em\=\CSbf[\red]{naturalloop} [\csbf[\copper]{MyCommand}]\textbf{\{3\}}\{\prmb{argument}\} \\
+% will expand to:\\
+% \> \Underbrace{\csbf[\copper]{MyCommand} \{\Underbrace{\csbf[\copper]{MyCommand} \{\Underbrace{\csbf[\copper]{MyCommand} \{\prmb{argument}\}}_{expanded first}\}}_{expanded second}\}}_{expanded last}
+% \end{tabbing}
+% \end{framed}
+% \csbf{MyCommand} should be purely expandable.
+% \ClearPage
+% In fact, it's a bit more sophisticated: \csbf{MyCommand} should be defined as:
+% \begin{VerbLines}[commandchars=!()]
+% (!copper\MyCommand):macro [!#1]!#2!#3 -> (!normalfont!bfseries Something to do with !#1 !#2 and !#3)
+%!normalfont Where:
+% !#1: (!normalfont is the current index of the loop (1, 2, 3 until to n))
+% !#2: (!normalfont is the original !prm(argument))
+% !#3: (!normalfont is the result of the recursion :ie) \do{\do{\do{\do{!prm(argument)}}}}
+% (!normalfont f.ex. in loop of index 4.)
+%\end{VerbLines}
+%
+% If you want a list of integers from 17 to 24 separated by semi-colon:
+% \begin{VerbLines}[commandchars=!()]
+% \def\do[#1]#2#3{#3 ; \number\numexpr#2+#1}
+% \naturalloop{7}{17} (!nnn !smex 17 ; 18 ; 19 ; 20 ; 21 ; 22 ; 23 ; 24)
+%\end{VerbLines}
+%
+% Another example is given in the \cmdref{ExpandNext} section.
+%
+% \end{ltxsyntax}
+%
+%
+% \Subsection{Lists of single tokens / characters} \cmdlabel{list of single tokens}
+%
+% Lists of single tokens are a special case of lists: they have no separator. The test for equalty of tokens
+% is made by \csbf[\red]{ifx} and therefore, finding a token in a list of single tokens is always a purely expandable operation.
+%
+% A \textsfbf{\slshape list of single tokens} is a list of \textitbf{single} tokens: that means you can't group them with braces
+% (the list may contain the |\bgroup| and |\egroup| tokens however).
+%
+% Lists of single tokens may also be tested with a special test which is |\ifx| in case of control sequences and
+% a detokenized-|\if| in case of single characters.
+%
+% Lists of single characters are used for testing \textsl{modifiers} in a purely expandable way. \textsfbf{\slshape modifiers} are
+% a vectorialisation of \cs{FE@ifstar} (and \cs{FE@ifchar}).
+%
+% \begin{ltxsyntax}
+%
+% \ClearPage
+% \cmditem[ifintokslist]+@{ifintokslist\tsptb ifincharlist}
+% \cmditem-{ifintokslist}{ single token }{ list of single tokens }{ true }{ false } \FEII*
+% \cmditem-{ifincharlist}{ single token }{ list of single tokens }{ true }{ false } \FEII*
+%
+% \csbf{ifintokslist} will switch\FEII to \prm{true} if the \prm{single token} is found
+% in the \prm{list of single tokens} while testing against each token of the list using \csbf{ifx}.
+%
+% {\rmk\cs{ifintokslist} could be tested with |\ifnum\getokslistindex{|\prm{token}|}{|\prm{list of tokens}|}|
+% but \cs{ifintokslist} optimises the loop in case the token is in the list.}
+%
+% \csbf{ifincharlist} will expands \prm{true} if the \prm{single token} is found in the \prm{list of single tokens}
+% but the test for equality of tokens is the \cmdref={character-test}.
+%
+% \end{ltxsyntax}
+% \ClearPage*
+%
+% Therefore, \cs{ifincharlist} behaves as follow:§§
+% \begin{VerbLines}[commandchars=$()]
+% \begingroup \catcode`\!=13 \catcode`\.=8 \catcode`\: 3
+% \global\def($copper\mylist){($blue:!\relax=.0)} ($nbf|) ($red\ifintokslist)
+% \endgroup $nbf|
+% $cs(expandnext){($red\ifincharlist)($blue!)}($copper\mylist){true}{false} $nbf true | false
+% \expandnext{($red\ifincharlist)($blue0)}($copper\mylist){true}{false} $nbf true | true
+% \expandnext{($red\ifincharlist)($blue:)}($copper\mylist){true}{false} $nbf true | false
+% \expandnext{($red\ifincharlist)($blue\relax)}($copper\mylist){true}{false} $nbf true | true
+% \end{VerbLines}
+%
+% {\rmk \cs{ifincharlist} is used in the definition of \cmdref{futuredef}.}
+%
+% \begin{ltxsyntax}
+% \cmditem+{gettokslistindex}{item}{list of single tokens}
+%
+% \csbf{gettokslistindex}\FEII expands to the index of \prmb{item} in the list of single tokens given as a second argument.
+%
+%
+% \textbf{Note that the \opt{index} is $\mathbf0-$based} for consistency with |\ifcase| ({\mdfs and also with
+% \cmdref{ettl@supergobble}}).
+% \ClearPage
+%
+% It is possible to say:§§\makeatletter\setbox\helpbox\hbox{\colorbox{yellow}{\vbbf 3}}\setbox\helpboxx\hbox{\colorbox{yellow}{\vbbf -1}}
+% \begin{VerbLines}[commandchars=!\[\]]
+% \newcount[!copper\result]
+% [!copper\result] = [!red\gettokslistindex]{d}{abcdef} !smex \result=!box!helpbox
+% \ifcase [!red\gettokslistindex]{d}{abcef}
+% [!nnn what to do if ] a
+% \or [!nnn what to do if ] b
+% \or [!nnn what to do if ] c
+% \or [!nnn etc. etc. etc.]
+% \else [!nnn what to do if] d [!nnn is not in the list:] !smex result=!box!helpboxx
+% \fi
+% \end{VerbLines}
+% \makeatother
+%
+% Please, refer to the examples...
+%
+% This feature is extensively used in \cmdref{FE@modifiers}.
+%
+% {\rmk \cmdref*{gettokslistindex} is kind of masterpiece of purely expandable programming with \eTeX}
+%
+% \cmditem+{getcharlistindex}{item}{list of single tokens}
+%
+% \csbf{getcharlistindex}\FEII expands to the index of \prmb{item} in the list of single tokens
+% (the index is $\mathbf0$ for the first item, $\mathbf{-1}$ if \prm{item} is not in the list).
+% The character-test is used instead of |\ifx| (see \cmdref{ifincharlist}).
+%
+% {\rmk \cmdref{getcharlistindex} is used - indirectly - in the definition of \cmdref{FE@modifiers}.}
+%
+% \ClearPage
+% \cmditem[gettokslistcount] @{gettokslistcount/token}
+% \cmditem-{gettokslistcount}{list of single tokens} \FEII*
+% \cmditem-{gettokslisttoken}{item}{list of single tokens} \FEII*
+%
+% \csbf{gettokslistcount},\FEII \csbf{gettokslisttoken} and \csbf{gettokslistindex} work all three with
+% the same engine, and this is also the case for \cmdref{getcharlistcount}, \cmdref{getcharlisttoken} and \cmdref{getcharlistindex}.
+% All are fully expandable.
+% \ClearPage
+%
+% \cs{gettokslistcount} gives the number of tokens in the list, while \cs{gettokslisttoken} should be seldom used (but
+% it was natural to define it as well).§§
+% \begin{VerbLines}[commandchars=!(),fontseries=m]
+% (!nnn if you say:) \let(!dg\plus) = !stform[!blue]+
+% (!red\gettokslisttokens){(!dg\plus)}{ABCD!stform[!blue]+EFG} (!nnn will expand to: )!stform[!blue]+
+% (!nnn and:)
+% (!red\gettokslisttokens){!stform[!blue]+}{ABCD(!dg\plus) EFG} (!nnn will expand to: )!dg\plus
+% \end{VerbLines}
+%
+% The idea is to loop into the list, testing each token of the list against \prm{item} with |\ifx|.
+% The \textsl{test-macro} (together with its own parameters) is a parameter of the \textsl{loop-macro},
+% and therefore, it can be changed without redefining it. As a result, the loop is purely expandable.
+%
+% Finally, when the loop is finished, the test macro becomes the \textsl{give-result-macro} (without |\let|)
+% and its own parameters are \textsl{extracted using projections} (like |\@firstoftwo|).
+%
+% The parameters of the \textsl{test-macro} include:
+% \begin{enumerate}[label=--~]
+% \item the current index in the list
+% \item the index of the \prm{item} found if |\ifx| returned \textvb{true}
+% \item the name of the \textsl{test-macro} to use at the next iteration. Usually it is the \textsl{test-macro}
+% itself, but for the last token in the list, this parameter is the \textsl{give-result-macro}.
+% \end{enumerate}
+%
+% Definition of \cmdref*{ettl@getsinglelist} worth a close look!
+%
+% Back to the begining: lists of single tokens are also lists without separator. Therefore, the other standard
+% macros \cmdref{toksloop} is provided by the general constructor
+% \cmdref{DeclareCmdListParser} invoked with an empty separator.
+%
+% {\rmk Unlike \cmdref{getlistindex}, \cmdref{getcsvlistindex} etc., \cs{gettokslistindex}, \cs{gettokslistcount}
+% and \cs{gettokslisttoken} have no star form nor optional parameter. This is because we might be able to test:§
+% ¤¤|\gettokslistindex{*}{|\prm{list of single tokens}|}|¤¤or¤¤|\gettokslistindex{[}{|\prm{list of single tokens}|}|§
+% and \cmdref{FE@ifstar} or \cmdref{FE@testopt} don't allow this. }^^A]
+% \ClearPage
+%
+% \cmditem[getcharlisttoken]@{getcharlistcount/token}
+% \cmditem-{getcharlistcount}{list of single tokens} \FEII*
+% \cmditem-{getcharlisttoken}{item}{list of single tokens} \FEII*
+%
+% They work\FE the same way as the \textsf{-tokslist} versions but with the \cmdref[ifincharlist]{character test}.
+%
+% {\rmk \cs{getcharlistcount} is exactly the same as \cs{gettokslistcount} and is {\rred2}-expandable.}
+%
+% \end{ltxsyntax}
+% \bigskip
+%
+% \Subsection[The General Command-List-Parser]{The General Command-List Parser Constructor}
+%
+% The \xpackage{etoolbox} package provides a way to define list parsers as fully expandable macros:
+% the list parser is able to expand the auxiliary command |\do| on each item of a list.
+% \iffalse
+% Declaration of a list parser is done via the |\DeclareListParser| macro\footnotemark.
+% \footnotetext{besides, \xpackage{etoolbox} defines the \xpackage{\textbackslash docsvlist} and the
+% \xpackage{\textbackslash dolistloop} macros: the choice of this name is not very friendly
+% and we expected to have a \xpackage{\textbackslash docsvloop} macro instead...}.
+% \fi
+%
+% Here we provide a |\DeclareCmdListParser| macro that is compatible and slightly different, because \textbfsf{the auxiliary
+% command is not necessarily \csbf{do}.} Such a command-list-parser is fully expandable.
+%
+% The idea is that if \cmdref{csvloop} has been defined as a command-list-parser then, thank to the fully expandable macro
+% \cmdref{FE@testopt} we can call for expansion:
+% \begin{tabbing}
+% \qquad\= |\csvloop|\itemitemitem[{\stform[\blue],}]\,\= as a shortcut for\,\= |\csvloop[\do]|\itemitemitem[{\stform[\blue],}]\\
+% or:\> |\csvloop[\listadd\mylist]|\itemitemitem[{\stform[\blue],}]
+% \end{tabbing}
+% for example to convert the csv-list into internal \xpackage{etoolbox} list.
+%
+% {\rmk The star-form of \cmdref{csvloop} will be explained below.}
+%
+% \begin{ltxsyntax}
+% \ClearPage
+%
+% \cmditem+{DeclareCmdListParser}[\cs{global}]{ command }{ separator }
+% \cmditem-{breakloop}{ code } \FE*
+%
+% |\DeclareCmdListParser| acts\notFE\ in the same way as \xpackage{etoolbox}-|\DeclareListParser| and the
+% command-list-parsers defined are sensitive to the category codes of the \prm{separator}. This
+% \prm{separator} may be any sequence of tokens, but the special sequence:§
+% \hfill\colorbox{ly}{$/__8$E$__{11}$n$__{11}$d$__{11}\S__7$L$__{11}$i$__{11}$s$__{11}$t$__{11}$/$__8$}\hfill\kern0pt§
+% which is used as the end-of-list-delimiter for any list.
+%
+% As long as \cmdref*{ettl@nbk} is used to check the end of the list, \CH{\chcat/8} is not
+% allowed in the list as well. Therefore, you may not try to define lists with \CH{\chcat/8} as separator:
+% they are \textsfsl{useless}\footnote{Unfortunately, \cmdref*{ettl@nbk} requires a single character as a delimiter... The choice for
+% \CH{\chcat/8} is explained in the \cmdref=[catcode choice]{implementation part.}}.
+%
+% To declare a new command-list-parser with \CH{\ttbf\blue,} (with the current catcode) as a separator you say:§§
+% \begin{VerbLines}[commandchars=!()]
+% (!red\DeclareCmdListParser)(!copper\myParser){(!blue,)}
+% \end{VerbLines}
+% \ClearPage*
+%
+% \begin{framed}
+% The Command-List-Parser declared: (here \csbf[\copper]{MyParser})
+% \begin{enumerate}[label=\smex,labelsep=.7em]
+% \item is a \textbfsf{purely expandable macro} with three modifiers (\stform*, \stform+ and \stform!)
+% an optional parameter (the \textbfsf{\slshape auxiliary macro} whose default is \csbf{do})
+% and a mandatory argument (the expanded List or the List-macro)
+% \item iterates into the list, giving each element to the \textslbf{\sffamily auxiliary macro}
+% \item the \textsfbf{\slshape auxiliary macro} must be of one of the following form: \\[1ex]
+% \hspace*{-\leftmargin}\begin{tabular}{l>{\sfbf}r@{}c@{}c>{\small}l}\hdashline[1pt/1pt]
+% \cs[\copper]{MyParser} & macro:\#1 & -> & |{| something to do with \#1|}| & \makecell{\#1 is an element \\ of the list} \\ \hdashline[1pt/1pt]
+% \cs[\copper]{MyParser}{\stform+} & macro:[\#1]\#2 & -> & |{ " " " |\#1 and \#2|}| & \makecell{\#1 is the index \\ and \#2 the element} \\ \hdashline[1pt/1pt]
+% \cs[\copper]{MyParser}{\stform!} & \multicolumn{3}{l}{expands to the number of elements in the list\bottopstrut} \\ \hdashline[1pt/1pt]
+% \end{tabular}
+% \end{enumerate}
+% \end{framed}
+%
+% The default is to define command-list-parsers \textbfsf{globally}, in order to make easier the
+% modifications of category code inside a group: if you wish \CH{\ttbf\blue+\black$_8$} to be the separator of your list,
+% you will say:§
+% \begin{VerbZ}[commandchars=!()]
+% \begingroup\catcode`\(!blue+)=8
+% (!red\DeclareCmdListParser)(!copper\MyParser){(!blue+)}
+% \endgroup
+% \end{VerbZ}
+%
+% {\rmk If you rather like a locally-defined command-list-parser, it is always possible, specifiying an empty option:
+% ¤¤|\DeclareCmdListParser|\textvb[\red]{[]}|\MyLocalParser{+}|.¤ The default option is |\global|, command-list-parsers are
+% always |\long| macros.}
+% \ClearPage
+%
+% You may then use the following syntaxes:§§
+% \newcommand\UserCmd{[\cs[\dg]{UserCommands}]}
+% \begin{VerbLines}[commandchars=$()]
+% ($copper\MyParser) \myList
+% ($nnn or:) ($copper\MyParser) $UserCmd\myList
+% ($nnn or:) ($copper\MyParser)$stform+ \myList
+% ($nnn or:) ($copper\MyParser)$stform+ $UserCmd\myList
+% ($nnn or:) ($copper\MyParser) $itemitemitem
+% ($nnn or:) ($copper\MyParser) $UserCmd$itemitemitem
+% ($nnn or:) ($copper\MyParser)$stform+ $itemitemitem
+% ($nnn or:) ($copper\MyParser)$stform+ $UserCmd$itemitemitem
+% ($nnn or:) ($copper\MyParser) [$stform(n)]\myList ($nnn expands to item$textsubscript(n))
+% ($nnn or:) ($copper\MyParser) [$stform(n)]$itemitemitem ($nnn expands to item$textsubscript(n))
+% ($nnn or:) ($copper\MyParser)$stform! \myList ($nnn expands to the number of elements)
+% ($nnn or:) ($copper\MyParser)$stform! $itemitemitem ($nnn expands to the number of items)
+%
+% ($nnn or:) $mdfs($copper\MyParser)$stform* $itemitemitem
+% ($nnn or:) $mdfs($copper\MyParser)$stform* $UserCmd$itemitemitem
+% ($nnn or:) $mdfs($copper\MyParser)$stform+$stform*$itemitemitem
+% ($nnn or:) $mdfs($copper\MyParser)$stform+$stform*$UserCmd$itemitemitem
+% ($nnn or:) $mdfs($copper\MyParser)$stform*$stform!$UserCmd$itemitemitem
+% \end{VerbLines}
+%
+% It's possible to break the loop by saying \csbf[\red]{breakloop} in your \cs[\dg]{UserCommands}. \csbf{breakloop} will
+% gobble anything until the end-of-list delimiter
+% (\footnotesize\colorbox{ly}{$/__8$E$__{11}$n$__{11}$d$__{11}\S__7$L$__{11}$i$__{11}$s$__{11}$t$__{11}$/$__8$})
+% and will append the \textbf{mandatory} parameter \prmb{code} after.
+%
+% \CH{\stform+\stform*} and \CH{\stform*\stform+} are identical, as well as \CH{\stform!\stform*} and \CH{\stform*\stform!}.
+% \ClearPage
+%
+% The \textbfsf{star-form} of \cs[\copper]{MyParser} \textbfsf{is seldom used:} \cs[\copper]{MyParser} abide by the following rules:
+% \begin{enumerate}[label=\roman*)~]
+% \item it checks if the list parameter (here \cs{mylist} or |{item|\mysep|item|\mysep|item}| is a single control word
+% (\cmdref{ifiscs} does the job)
+% \item if this is a single control word, then it is expanded once
+% \item otherwise, no expansion of the list occurs
+% \end{enumerate}
+% \textsfsl{Therefore, the need for the \stform* form is only in the special case where
+% the \textbf{expanded List} contains a single control-word, not followed by a separator.}
+%
+% {\rmk The reader interested in macros with multiple modifiers which may be used in any order
+% can have a look at the definition of \cmdref*{ettl@lst@modif}.}
+%
+% Moreover, \cs{DeclareCmdListParser} defines a macro named \csbf{\ttbf\red for\copper MyParser} to do loops with a syntax
+% very close to \LaTeX's |\@for|: see \cmdref{forcsvloop} for more explanation.
+%
+% \end{ltxsyntax}
+%
+% \ClearPage
+% \Subsection{Loops into lists}
+%
+% The following macros are purely expandable loops into comma-separated lists (\cs{csvloop}),
+% \xpackage{etoolbox} list (\cs{listloop}) and token lists (lists of tokens without a separator).
+%
+% All of them are defined using \cmdref{DeclareCmdListParser}.
+%
+% \begin{ltxsyntax}
+% \ClearPage
+%
+% \cmditem[csvloop]+@{csvloop\tsptb csvloop\stform+\tsptb csvloop\stform!}
+% \cmditem-{csvloop}[ auxiliary commands ]{ csvlist-macro \textsfsl{or} \itemitemitem*[{\stform[\blue],}]} \FE*
+% \cmditem-{csvloop\stform+}[ auxiliary commands ]{ csvlist-macro \textsfsl{or} \itemitemitem*[{\stform[\blue],}]} \FE*
+% \cmditem-{csvloop\stform!}[ auxiliary commands]{ csvlist-macro \textsfsl{or} \itemitemitem*[{\stform[\blue],}]} \FE*
+% \cmditem-{csvloop\stform*}[ auxiliary commands ]{ \itemitemitem*[{\stform[\blue],}] } \FE*
+% \cmditem-{csvloop\stform*\stform+}[ auxiliary commands]{ \itemitemitem*[{\stform[\blue],}] } \FE*
+% \cmditem-{csvloop\stform*\stform!}[ auxiliary commands]{ \itemitemitem*[{\stform[\blue],}] } \FE*
+%
+% Examples:\FE §§
+% \begin{VerbLines}[commandchars=$()]
+% ($red\csvloop)($copper\mylist) ($nnn is the same as:) ($red\csvloop)($blue[\do])($copper\mylist)
+% ($nnn and applies ($blue$CSbf(do)) sequentially to each element of the comma-separated list.)
+% ($nnn($blue$CSbf(do)) is a user command of the form:)
+% macro: $#1 -> {($nnn something to do with ($vbbf$#1 = item)) }
+% ($nnn The star form ($red$vbbf\csvloop$stform[$rred]*) ($nitbf may be) used when ($vbbf$copper\mylist) is already expanded.)
+% ($nnn The plus form ($red$vbbf\csvloop$stform[$rred]+) ($nitbf is) used when) $CSbf[$blue](do) ($nnn is of the form:)
+% macro: [$#1]$#2 -> {($nnn something to do with ($vbbf$#1=index) and ($vbbf$#2=item)) }
+% ($nnn If) $CSbf[$blue](do) ($nnn is in fact a number:)
+% ($red\csvloop)[($blue4)]($copper\mylist) ($nnn will expand to the($nitbf fifth) element of )($copper\mylist)
+% ($red$vbbf\csvloop$stform[$rred]!)($copper\mylist) ($nnn will expand to the number of elements in) ($copper\mylist)
+% \end{VerbLines}
+%
+% \textbfsf{Be aware that indexes in lists are 0-based: they begin with 0.}
+%
+% Remember that the \stform* form is seldom used: you probably will forget it!
+%
+% \cmditem[listloop]@{listloop\tsptb listloop\stform+\tsptb listloop\stform!}
+% \cmditem-{listloop}[ auxiliary commands ]{ Listmacro or expanded List } \FE*
+% \cmditem-{listloop\stform+}[ auxiliary commands ]{ Listmacro or expanded List } \FE*
+% \cmditem-{listloop\stform!}[ auxiliary commands ]{ expanded List } \FE*
+% \cmditem[listloop*]-{listloop\stform*(\stform+)(\stform!)}[ auxiliary commands ]{ expanded List } \FE*
+%
+% \csbf{listloop}\FE is designed to work with \xpackage{etoolbox} lists (lists with \CH{\stform[\blue]\textbar$_3$} as separator).
+% \cs{listloop} enhances \xpackage{etoolbox}-|\dolistloop| with an optional argument to change
+% the default auxiliary command |\do| to apply to each item of the list, a \stform+ form a \stform! form and a \stform* form.
+% It behaves exactly as \cmdref{csvloop} does.
+%
+% \cmditem[toksloop]@{toksloop\tsptb toksloop\stform+\tsptb toksloop\stform!}
+% \cmditem-{toksloop}[ auxiliary commands ]{ tokenslistmacro or list of single tokens } \FE*
+% \cmditem-{toksloop\stform+}[ auxiliary commands ]{ tokenslistmacro or list of single tokens } \FE*
+% \cmditem-{toksloop\stform!}[ auxiliary commands ]{ tokenslistmacro or list of single tokens } \FE*
+% \cmditem[toksloop*]-{toksloop\stform*(\stform+)(\stform!)}[ auxiliary commands ]{ list of single tokens } \FE*
+%
+% \csbf{toksloop}\FE is a list parser for lists without separator (\cmdref={list of single tokens}).
+%
+% With \cs{toksloop} you are able to count the number of characters in a string:§§
+% \begin{VerbLines}[commandchars=$()]
+% ($red\toksloop$stform[$rred]!){abcdef} $smex 6
+% \end{VerbLines}
+% Spaces are not counted, however...
+% \ClearPage*
+%
+% \cmditem[forcsvloop]+@{forcsvloop\tsptb forcsvloop\stform+}
+% \cmditem[forlistloop]@{forlistloop\tsptb forlistloop\stform+}
+% \cmditem[fortoksloop]@{fortoksloop\tsptb fortoksloop\stform+}
+% \cmditem-{forcsvloop}{ csvlistmacro \textsfsl{or} \itemitemitem*[{\stform[\blue],}]}|\cs[\spot]{do}\{\prm{...\#1...}\}|
+% \cmditem-{forlistloop}{ Listmacro \textsfsl{or} expanded List }|\cs[\spot]{do}\{\prm{...\#1...}\}|
+% \cmditem-{fortoksloop}{ tokenslistmacro \textslsf{or} list of single tokens }|\cs[\spot]{do}\{\prm{...\#1...}\}|
+% \cmditem-{forcsvloop\stform+}{ csvlistmacro \textsfsl{or} \itemitemitem*[{\stform[\blue],}]}|\cs[\spot]{do}\{\prm{...\#1=index...\#2=element...}\}|
+% \cmditem-{forlistloop\stform+}{ Listmacro \textsfsl{or} expanded List }|\cs[\spot]{do}\{\prm{...\#1=index...\#2=element...}\}|
+% \cmditem-{fortoksloop\stform+}{ tokenslistmacro \textslsf{or} list of single tokens }|\cs[\spot]{do}\{\prm{...\#1=index...\#2=element...}\}|
+% \cmditem-{forcsvloop\stform*(\stform+)}{\itemitemitem*[{\stform[\blue],}]}|\cs[\spot]{do}\{\prm{...\#1...}\}|
+% \cmditem-{forlistloop\stform*(\stform+)}{ expanded List }|\cs[\spot]{do}\{\prm{...\#1...}\}|
+% \cmditem-{fortoksloop\stform*(\stform+)}{ list of single tokens }|\cs[\spot]{do}\{\prm{...\#1...}\}|
+%
+% Those macros\notFE\ are just like \cmdref{csvloop}, \cmdref{listloop} and \cmdref{toksloop} but the syntax is quite the
+% same as \LaTeX's \CSbf{@for}, but instead of giving a name to the current item being parsed, it is \#1! (or \#2 with the \stform+ form).
+%
+% |forloop| construct may by nested. Here is an example (merely silly):
+% \begin{tabbing}
+% \qquad\=|\forcsvloop|\stform*|{|\=|\relax\meaning|\=|\csname|\=|,%|\\
+%\>\> |\afterassignment\global\count,%|\\
+% \>\>|\endgroup\topskip}\do{%|\\
+% \>\>\> |\fortoksloop|\stform*|{|\#1|}\do{\meaning|\#{\#1}|}}|
+% \end{tabbing}
+%
+% Of course, those macros are NOT purely expandable... They are automatically defined by \cmdref{DeclareCmdListParser}
+% with the name: \csbf{\red for\md\copper name-of-parser}.
+%
+% The \stform+ form of \cs{forcsvloop} et al. are relative to the \stform+ form of \cs{csvloop} et al.:
+% \#1 is the index and \#2 the element. There is no \stform! form.
+%
+% \end{ltxsyntax}
+%
+% \Subsection{Adding elements to csv lists}
+%
+% \thispackage provides a facility to add items to a csvlist.
+% \begin{ltxsyntax}
+% \cmditem[csvlistadd]@{csvlistadd/gadd/eadd/xadd}
+% \cmditem-{csvlistadd}{ csvListmacro }{ item }
+% \cmditem-{csvlistgadd}{ csvListmacro }{ item }
+% \cmditem-{csvlisteadd}{ csvListmacro }{ item }
+% \cmditem-{csvlistxadd}{ csvListmacro }{ item }
+%
+% \csbf{csvlistadd}\notFE adds an item to a csvlist. \cs{csvlisteadd} expands the \prm{item}
+% (with |\protected@edef|) \textsfbf{before} appending it to \prm{csvListmacro}, whilst with \cs{csvlistgadd}
+% the final assignment to \prm{csvListmacro} is global. Finally, \cs{csvlistxadd} both expands the \prm{item}
+% and makes the assignment global.
+%
+% These macros are robust.
+% \end{ltxsyntax}
+% \ClearPage\enlargethispage{2\baselineskip}
+%
+% \Subsection{Converting lists}
+%
+% Since \cmdref=[DeclareStringFilter]{string filters} are sensitive to the category code of the caracters, it is always possible
+% to convert lists (\ie changing their separator) using them. For exemple, if one wish to convert a comma separated list into
+% a list with \CH{\stform[\blue]\&$_4$} as separator one may say:§§
+% \begin{VerbLines}[commandchars=!()]
+% \def(!copper\mycsvlist){one,two,three,four,five}
+% \DeclareStringFilter(!vbbf\CompareComma){!stform[!blue],}
+% (!dg\begingroup) \catcode`\!stform[!blue]& = 4 (!nsl this is its standard catcode anyway)
+% (!dg\xdef)(!copper\myNewList){(!red\expandnext){(!vbbf\CompareComma+)}(!copper\mycsvlist){!stform[!blue]&}}
+% (!dg\endgroup)
+% \end{VerbLines}
+% But there is another way, may be easier:§§
+% \begin{VerbLines}[commandchars=!()]
+% (!dg\begingroup) \catcode`\!stform[!blue]& = 4 (!nsl this is its standard catcode anyway)
+% (!dg\global\def)(!red\do)#1{\unexpanded{#1!stform[!blue]&}}
+% (!dg\endgroup)
+% (!dg\edef)(!copper\myNewList){\csvloop[(!red\do)](!copper\mycsvlist)}
+% \end{VerbLines}
+%
+% Nevertheless, some conversions could be used very often and \thispackage provides a few macros to convert
+% lists easily:
+%
+% \begin{ltxsyntax}
+% \ClearPage
+%
+% \cmditem[csvtolist]@{csvtolist\tsptb tokstolist\tsptb listtocsv}
+% \cmditem-{csvtolist}[ target: Listmacro ]{ source: csvlistmacro \textsfsl{or} \itemitemitem*[{\stform[\blue],}]}
+% \cmditem-{csvtolist\stform*}[ target: Listmacro ]{ source: \itemitemitem*[{\stform[\blue],}] } \FE*
+%
+% \csbf{csvtolist}\FE converts a comma separated list into an internal \xpackage{etoolbox} list. It is useful to insert more than one item
+% at a time in a list. The \prm{Listmacro} (target parameter) is optional and the user may prefer obtain the result in an |\edef|:§§
+% \begin{VerbLines}[commandchars=!()]
+% (!red\csvtolist)[(!copper\myList)]{one,two,three}
+% (!nnn is the same as:)
+% (!dg\edef)(!copper\myList){(!red\csvtolist){one,two,three}}
+% (!nnn if you want )(!copper\myList)(!nnn to be global, use the second form with )(!dg\xdef)(!nnn instead of )(!dg\edef).
+%(!nnn!rmk* N.B.: the items are not expanded.)
+% \end{VerbLines}
+%
+% The \stform* star form is seldom used: it is there to inhibits the expansion of \prm{source: \itemitemitem*[{\stform[\blue],}]}.
+% But expansion occurs only if this parameter is a single control word...
+% \ClearPage
+%
+% \cmditem[tokstolist]-{tokstolist} [ target: Listmacro ]{ source: tokenslistmacro \textsfsl{or} list of single tokens }
+% \cmditem-{tokstolist\stform*}[ target: Listmacro ]{ source: list of single tokens } \FE*
+%
+% \csbf{tokstolist}\FE converts a list of tokens (no separator) into an internal \xpackage{etoolbox} list:§§
+% \newcommand\etbsep{\stform[\blue]\textbar$__3$\!\!\!}
+% \begin{VerbLines}[commandchars=!()]
+% (!red\tokstolist)[(!copper\myList)]{\alpha\beta\gamma\ifeof+*$}
+% (!nnn is the same as:)
+% (!dg\edef)(!copper\myList){(!red\tokstolist){\alpha\beta\gamma\ifeof+*$}}
+% \meaning\myList: macro:->\alpha!etbsep \beta!etbsep \gamma!etbsep \ifeof!etbsep +!etbsep *!etbsep $!etbsep
+% (!nnn if you want )(!copper\myList)(!nnn to be global, use the second form with )(!dg\xdef)(!nnn instead of )(!dg\edef).
+%(!nnn!rmk* N.B.: the items are not expanded.)
+% \end{VerbLines}
+%
+% This is also the first application of the \cmdref{toksloop} macro just defined.
+%
+% \cmditem[listtocsv]-{listtocsv}[ target: csvlistmacro ]{ source: Listmacro \textsfsl{or} expanded List }
+% \cmditem-{listtocsv\stform*}[ target: csvlistmacro ]{ source: Listmacro \textsfsl{or} expanded List } \FE*
+%
+% \csbf{listtocsv}\FE converts an \xpackage{etoolbox}-List into a comma separated list. Be aware that the items in the
+% list does not contain commas (\cs{listtocsv} does not check this point!):§§
+% \begin{VerbLines}[commandchars=!()]
+% (!red\listtocsv)[(!copper\csvList)]\etbList !nnn is the same as:
+% \edef(!copper\csvList){(!red\listtocsv)\etbList}
+% (!nnn if you want )(!copper\csvList)(!nnn to be global, use the second form with )(!dg\xdef)(!nnn instead of )(!dg\edef).
+%(!nnn!rmk* N.B.: the items are not expanded.)
+% \end{VerbLines}
+%
+% \cmditem[csvtolistadd]@{csvtolistadd\tsptb tokstolistadd}
+% \cmditem-{csvtolistadd}{ target: Listmacro }{ source: csvlistmacro \textsfsl{or} \itemitemitem*[{\stform[\blue],}]}
+% \cmditem-{csvtolistadd\stform*}{ target: Listmacro }{ source: \itemitemitem*[{\stform[\blue],}] }
+%
+% \csbf{csvtolistadd}\notFE\ acts similarly but both arguments are mandatory:§§
+% \begin{VerbLines}[commandchars=!(),codes={\catcode`\$=3}]
+% \listadd(!copper\myList){one} \listadd(!copper\myList){two}
+% (!red\csvtolistadd)(!copper\myList){three,four,five}
+% \meaning\myList: macro:->one!etbsep two!etbsep three!etbsep four!etbsep five!etbsep
+% \end{VerbLines}
+%
+% \cmditem[tokstolistadd]-{tokstolistadd} { target: Listmacro }{ source: tokenslistmacro \textsfsl{or} list of single tokens}
+% \cmditem-{tokstolistadd\stform*}{ target: Listmacro }{ source: list of single tokens }
+%
+% \csbf{tokstolistadd}\notFE\ acts similarly but both arguments are mandatory.
+%
+% The \stform* star-form inhibits the expansion of \prm{source} (which otherwise occurs only if \prm{source}
+% is a single control word).
+%
+% \end{ltxsyntax}
+% \ClearPage*
+%
+% \Subsection{Test if an element is in a list}
+%
+% \xpackage{etoolbox} provides \cmd{ifinlist} and \cmd{xifinlist}. Similarly, \thispackage provides:
+%
+% \begin{ltxsyntax}
+%
+% \cmditem[ifincsvlist]@{ifincsvlist\tsptb xifincsvlist}
+% \cmditem-{ifincsvlist}{ item }{ csvlistmacro \textsfsl{or} \itemitemitem*[{\stform[\blue],}]}{ true }{ false }
+% \cmditem-{xifincsvlist}{ item }{ csvlistmacro \textsfsl{or} \itemitemitem*[{\stform[\blue],}]}{ true }{ false } \notFE*
+% \cmditem-{ifincsvlist\stform*}{ item }{ \itemitemitem*[{\stform[\blue],}]}{ true }{ false}
+% \cmditem-{xifincsvlist\stform*} { item }{ \itemitemitem*[{\stform[\blue],}]}{ true }{ false}
+%
+% These macros\notFE\ are not purely expandable. The search is sensitive to the category code
+% of the characters in \prm{item}.
+%
+% \end{ltxsyntax}
+%
+% \Subsection{Removing elements from lists}
+%
+% \subsubsection{\xpackage{etoolbox} lists}
+%
+% The \xpackage{etoolbox} package provides \cs{listadd}, \cs{listgadd}, \cs{listeadd} and \cs{listxadd} commands
+% to add items to a list. \thispackage provides \cs{listdel}, \cs{listgdel}, \cs{listedel} and \cs{listxdel} to
+% remove elements from a list.
+% \ClearPage
+%
+% \begin{ltxsyntax}
+%
+% \cmditem[listdel]+@{listdel/gdel/edel/xdel} \enlargethispage\baselineskip
+% \cmditem-{listdel}[ deleted $n$ times ]{ Listmacro }{ item }
+% \cmditem-{listgdel}[ deleted $n$ times ]{ Listmacro }{ item }
+% \cmditem-{listedel}[ deleted $n$ times ]{ Listmacro }{ item }
+% \cmditem-{listxdel}[ deleted $n$ times ]{ Listmacro }{ item }
+%
+% The \csbf{listdel}\notFE\ command removes the element \prm{item} from the list \prm{Listmacro}. Note that the
+% \prm{Listmacro} is redefined after deletion. If the list contains more than one element equal to \prm{item}
+% each is removed.
+%
+% \csbf{listedel} expands the \prm{item} (with |\protected@edef|) \textsfbf{before} deletion, whilst with \csbf{listgdel}
+% the final assignment to (the \emph{shortened}) \prm{Listmacro} is global. Finally, \csbf{listxdel} both expands the \prm{item}
+% and makes the assignment global.
+%
+% If the optional parameter \prm{deleted $n$ times} is specified as a control sequence, the macro does the same but
+% but assigns to this control sequence the number of times \prm{item} has been found in the list. If this parameter
+% is not a counter, it is (possibly \textit{re-})defined as a macro:§§
+% \begin{VerbLines}[commandchars=$()]
+% \newcount($dg\mycounter)
+% \def($copper\myList){one,two,($dgray$!$!$! three),two,($dgray$!$!$! three),four,five,($dgray$!$!$! three)}
+% ($red\listdel)[($dg\mycounter)]($copper\myList){($dgray$!$!$! three)}
+% \the($dg\mycounter) ($nnn will be ) 3
+% \end{VerbLines}
+%
+% \end{ltxsyntax}
+%
+% \subsubsection{csv-lists}
+%
+% \begin{ltxsyntax}
+%
+% \cmditem[csvdel] @{csvdel/gdel/edel/xdel}
+% \cmditem-{csvdel}[ deleted $n$ times ]{ csvlistmacro }{ item }
+% \cmditem-{csvgdel}[ deleted $n$ times ]{ csvlistmacro }{ item }
+% \cmditem-{csvedel}[ deleted $n$ times ]{ csvlistmacro }{ item }
+% \cmditem-{csvxdel}[ deleted $n$ times ]{ csvlistmacro }{ item }
+%
+% Are similar for\notFE\ comma-separated lists. Those macros are NOT purely expandable.
+%
+% \subsubsection{Lists of single tokens}
+%
+% \cmditem[toksdel]@{toksdel/gdel/edel/xdel}
+% \cmditem-{toksdel}[ deleted $n$ times ]{ tokslistmacro }{ item }
+% \cmditem-{toksgdel}[ deleted $n$ times ]{ tokslistmacro }{ item }
+% \cmditem-{toksedel}[ deleted $n$ times ]{ tokslistmacro }{ item }
+% \cmditem-{toksxdel}[ deleted $n$ times ]{ tokslistmacro }{ item }
+%
+% Are similar\notFE\ for lists of single tokens (lists without separator).
+%
+% \end{ltxsyntax}
+%
+% \Subsection{Index of an element in a list}
+%
+% \subsubsection{\xpackage{etoolbox}-lists}
+%
+% \begin{ltxsyntax}
+%
+% \cmditem{getlistindex}[result-index(counter or macro)]{item}{Listmacro}
+% ^^A\cmditem-{xgetlistindex}[result-index(counter or macro)]{item}{Listmacro}
+% \cmditem-{getlistindex*}[result-index(counter or macro)]{item}{list}
+% ^^A\cmditem-{xgetlistindex*}[result-index(counter or macro)]{item}{list}
+%
+% \end{ltxsyntax}
+%
+% Sometimes\notFE\ it is interesting to know at which offset in a list lies a given item. |\getlistindex| answers to this question.
+% |\xgetlistindex| does the same thing but expands the \prm{item} while looking for it in the list.
+%
+% As for the command-list-parser, the star versions are designed in case the list (in the second argument) is already expanded.
+%
+% \begin{itemize}
+% \item \ If \prm{item} is not found in the list, \cs{getlistindex} expands to 0
+% \item \ If \prm{item} is found in first position then \cs{getlistindex} expands to 1 and so on.
+% \end{itemize}
+%
+% Those macros are not purely expandable.
+%
+% N.B. If \prm{result-index} is not a counter it is (possibly \textit{re-})defined as macro.
+%
+% \subsubsection{Comma-separated lists}
+%
+% \begin{ltxsyntax}
+% \cmditem{getcsvlistindex}[result-index(counter or macro)]{item}{csvlistmacro}
+% ^^A\cmditem-{xgetcsvlistindex}[result-index(counter or macro)]{item}{csvlistmacro}
+% \cmditem-{getcsvlistindex*}[result-index(counter or macro)]{item}{item,item,item,...}
+% ^^A\cmditem-{xgetcsvlistindex*}[result-index(counter or macro)]{item}{item,item,item,...}
+% \end{ltxsyntax}
+%
+% This\notFE\ is the same as \cmdref{getlistindex} but for comma-separated lists.
+%
+% As for the command-list-parser, the star versions are designed in case the list (in the second argument) is already expanded.
+%
+% If \prm{result-index} is not a counter it is (possibly \textit{re-})defined as macro.
+%
+% \subsection[\texorpdfstring\blue{}Arithmetic: lists of numbers]{Arithmetic: lists of numbers}
+%
+% \begin{ltxsyntax}
+% \cmditem+{interval}{ number }{ sorted comma separated list of numbers }
+%
+% \csbf{interval}\FE will expand to the interval of \prm{number} into the \prm{sorted csv list of numbers}:§§
+% \begin{VerbLines}[commandchars=!()]
+% (!red\interval){0}{3,5,12,20} (!nnn will expand to ) 0
+% (!red\interval){3}{3,5,12,20} (!nnn will expand to ) 1
+% (!red\interval){4}{3,5,12,20} (!nnn will expand to ) 1
+% (!red\interval){5}{3,5,12,20} (!nnn will expand to ) 2
+% (!red\interval){19}{3,5,12,20} (!nnn will expand to ) 3
+% (!red\interval){20}{3,5,12,20} (!nnn will expand to ) 4
+% (!red\interval){21}{3,5,12,20} (!nnn will expand to ) 4
+% \end{VerbLines}
+%
+% \cmditem+{locinterplin}{ number }{ sorted csv list of numbers }{ csv list of numbers }
+%
+% \abovedisplayskip=2pt \belowdisplayskip=2pt
+%
+% \csbf{locinterplin}\FE will locally and linearly interpolate the series $Y_i$ in \prm{csv list of numbers}:§
+% \hfill \csbf[\red]{locinterplin}\mprm{\dg$X$}\mprm{\dg$X_i$}\mprm{\blue$Y_i$} \hfill\null
+% $$\llap{finds $i$ such that:¤¤} \dg X_i\leqslant X\leqslant X_{i+1}$$
+% and expands to the local linear interpolation $\blue Y$:
+% $${\blue Y} = {\blue Y_i} + \dfrac{\dg X-X_i}{\dg X_{i+1}-X_i} \left({\blue Y_{i+1}-Y_i}\right)$$
+%
+% $\dg X_i$ and $\blue Y_i$ must have the same number of elements.
+%
+% \end{ltxsyntax}
+%
+% \StopEventually{
+% }
+%
+% \part*{{\spot\smiley}\hfill \LaTeX{} code\hfill{\spot\smiley}}
+% \addtocontents{toc}{\protect\contentsline{part}{\LaTeX{} code}{}{}}
+% \implementationsubsecformat
+%
+% \Section*{Implementation} \refstepcounter{section}%
+% ^^A\addcontentsline{toc}{section}{\texorpdfstring\dr{}\hskip\dimexpr\cftsecnumwidth-4pt Implementation}^^A do not add to .cmd file
+% \addcontentsline{toc}{section}{\protect\numberline{I}\cftsecfont Implementation}^^A do not add to .cmd file
+% \addtocontents{toc}{\cftbeforesubsecskip=-2pt plus\gluestretch\cftbeforesubsecskip\relax
+% \renewrobustcmd\noexpand\cftsubsecfont{\footnotesize}}
+% \renewcommand\thesubsection{I.\arabic{subsection}}^^A for toc
+%
+% \Subsection{Package identification}
+%
+% \begin{macrocode}
+%<*package>
+\NeedsTeXFormat{LaTeX2e}[1996/12/01]
+\ProvidesPackage{etextools}
+ [2010/12/07 v3.1415926 e-TeX more useful tools for LaTeX package writers]
+\csname ettl@onlyonce\endcsname\let\ettl@onlyonce\endinput
+% \end{macrocode}
+%
+% \Subsection{Requirements}
+%
+% This package requires the packages \xpackage{etex} package by David Carlisle
+% \xpackage{etoolbox} by Philipp Lehman and \xpackage{letltxmacro} by Heiko Oberdiek (for \cmdref*{aftergroup@def}):
+%
+% \begin{macrocode}
+\RequirePackage{etex,etoolbox,letltxmacro}
+% \end{macrocode}
+%
+% The divide sign \CH{\stform[\rred]/} (or slash) is given a catcode of $\mathbf8$. \textbfsf{It is used as a delimiter.}
+% This choice is driven by three reasons:\cmdlabel{catcode choice}
+% \begin{enumerate}[label=\arabic*)~]
+% \item \CH{\stform[\rred]/} cannot be used in |\numexpr| expressions if its catcode is different of $12$,
+% making unlikely that someone changes its catcode in his document. However, the same is true
+% for \CH{\stform<}, \CH{\stform>}, \CH{\stform=}, \CH{\stform+}, \CH{\stform-} and \CH{\stform.} (for dimensions) but:
+% \item \CH{\stform[\rred]/} is not used in \thispackage but as a delimiter (whereas \CH+, \CH-, \CH<, \CH>, \CH= and \CH.
+% are used with their normal meaning).
+% \item but why {$\rred\mathbf8$} ? if someone changes the catcode of \CH{\stform[\rred]/} it is unlikely that she will choose
+% $\rred\mathbf8$ (the \textit{\rred math subscript} which has nothing to do with \stform[\rred]/...) whereas it is not so unlikely that
+% someone needs \CH{\stform[\rred]/} as a \emph{tab alignment character} (catcode $4$) or a \emph{math shift} (catcode $3$)
+% or another special need (catcode $13$)... Moreover, catcode $4$ may have indesirable side effects if read inside \cs{halign} or \cs{valign}.
+% Finally, we could have chosen {$\blue\mathbf7$} but then a sequence like: \CH{\stform[\blue]/$\mathbf{_7}$\stform[\blue]/$\mathbf{_7}$}
+% is read by \TeX{} like \CH{\stform[\blue]{\string^}$\mathbf{_7}$\stform[\blue]{\string^}$\mathbf{_7}$} with a very special meaning...
+% \end{enumerate}
+% Therefore, the choice might not be bad...
+% \begin{macrocode}
+\let\ettl@AtEnd\@empty
+\def\TMP@EnsureCode#1#2{%
+ \edef\ettl@AtEnd{%
+ \ettl@AtEnd
+ \catcode#1 \the\catcode#1\relax
+ }%
+ \catcode#1 #2\relax
+}
+\TMP@EnsureCode{32}{10}% space... just in case
+\TMP@EnsureCode{47}{8}% /
+\TMP@EnsureCode{167}{7}% §
+\TMP@EnsureCode{164}{7}% ¤
+\TMP@EnsureCode{95}{11}% _
+\TMP@EnsureCode{42}{12}% *
+\TMP@EnsureCode{43}{12}% +
+\TMP@EnsureCode{45}{12}% -
+\TMP@EnsureCode{46}{12}% .
+\TMP@EnsureCode{60}{12}% <
+\TMP@EnsureCode{61}{12}% =
+\TMP@EnsureCode{62}{12}% >
+\TMP@EnsureCode{33}{12}% !
+\TMP@EnsureCode{152}{13}% ~ for the character test
+\ifundef\pdfstrcmp{%
+ \TMP@EnsureCode{163}{9}% £ ignore
+ \TMP@EnsureCode{128}{14}% \texteuro comment €
+}{\TMP@EnsureCode{163}{14}% £ comment
+ \TMP@EnsureCode{128}{9}% \texteuro ignore
+}
+\AtEndOfPackage{\ettl@AtEnd\undef\ettl@AtEnd}
+% \end{macrocode}
+%
+% \Subsection{Some ``helper'' macros}
+%
+% \iffalse
+%<package>
+%<package>% A few helper macros
+% \fi
+%
+%\begin{macro}{helper macros} \FE
+% \begin{macrocode}
+\let\ettl@ifdefined\ifdefined%\ifdefined% turn to \iffalse to test other implementation on pdfTeX
+\long\def\ettl@fi#1\fi{\fi#1}
+\long\def\ettl@else#1\else#2\fi{\fi#1}
+\long\def\ettl@or#1\or#2\fi{\fi#1}
+\def\ettl@expandaftwo{\expandafter\expandafter\expandafter}
+\def\ettl@expandafthree{\expandafter\expandafter\expandafter%
+ \expandafter\expandafter\expandafter\expandafter}
+\cslet{ettl@1of1}\@firstofone %% for internal use only
+\cslet{ettl@1of2}\@firstoftwo %% for internal use only
+\cslet{ettl@2of2}\@secondoftwo %% for internal use only
+\long\def\rmn@firstoftwo#1#2{\z@#1} %% for romannumeral
+\long\def\rmn@secondoftwo#1#2{\z@#2}%% for romannumeral
+\long\def\ettl@cdr#1#2\@nil{#2} %% \@cdr should be a LONG macro
+\long\def\ettl@car#1#2\@nil{#1} %% \@car should be a LONG macro
+\long\csdef{ettl@1of3}#1#2#3{#1}
+\long\csdef{ettl@2of3}#1#2#3{#2}
+\long\csdef{ettl@3of3}#1#2#3{#3}
+\long\csdef{ettl@12of3}#1#2#3{{#1}{#2}}
+\long\def\ettl@carcar#1#2#3#4{#4}
+\long\def\ettl@firstspace#1#2#3{\expandafter\ettl@firstsp@ce\detokenize{#1} \\{#3}{#2}//}
+\long\def\ettl@firstsp@ce#1 #2\\{\ettl@nbk#1//}
+\long\def\ettl@csname#1\endcsname{\fi\endcsname}%% useful to get out of \if
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\ettl@char}
+% \cs{ettl@char} expands to \prm{true} if its argument is a single character token. It is used in
+% \cmdref*{ettl@ifnextchar}.
+% \begin{macrocode}
+\long\def\ettl@char#1{\csname ettl@\ifcat $\expandafter\ettl@cdr\detokenize{#1}\@nil$%
+ 1\else2\fi of2\endcsname}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\ettl@intmax}
+% This\FE is the maximum integer allowed by e\TeX{} for |\numexpr| ($2^31-1$) and all arithmetic operations:
+% \begin{macrocode}
+\providecommand*\@intmax{2147483647}
+\def\ettl@intmax{2147483647}
+% \end{macrocode}
+%\end{macro}
+%
+% \iffalse
+%<package>
+%<package>%% \ettl@onlypdfTeX for internal use
+% \fi
+%
+% \begin{macro}{\ettl@onlypdfTeX}
+% This is an \textit{internal macro} used by the package: if the \prm{primitive}
+% in \#1 is available (\eg \cs{pdfstrcmp}) then the \prm{command} in \#2
+% can be defined, otherwise, the \prm{command} is \cs{let} to the optional argument \#3.
+% If there is no such optional argument, the \prm{command} throws an error (\eg \cs{ifstrmatch}).
+% \begin{macrocode}
+\def\ettl@onlypdfTeX#1#2{\@testopt{\ettl@only@pdfTeX{#1}{#2}}{}}
+\def\ettl@only@pdfTeX#1#2[#3]{\ifundef{#1}
+ {\ifblank{#3}
+ {\def#2{\PackageError{etextools}{\string#1\space primitive not found\MessageBreak
+ pdfTeX seems not to be running}
+ {\string#2\space works only if used with pdfTeX (requires \string#1)}}}
+ {\AtEndOfPackage{\let#2=#3}%
+ \PackageWarning{etextools}{\string#1\space primitive not found\MessageBreak
+ Macro \string#2\space has been replaced by \string#3\space\MessageBreak
+ It is not purely expandable}}
+ }\relax}
+% \end{macrocode}
+% \end{macro}
+%
+% \iffalse
+%<package>
+%<package>%% \ettl@nbk argument to be tested//{ true }{ false }//
+%<package>% `/` has a catcode of 3 all along this package
+% \fi
+%
+% \begin{Macro*}{ettl@nbk}
+% \CSbf{ettl@nbk}\FEI is an optimized form of |\ifblank|. \TeX{} switches to the
+% \prm{true} part if the expanded argument (delimited by \CH{\chcat/8\chcat/8}) is
+% \txtbf[\rred]not \txtbf[\rred]blan\txtbf[\rred]k.
+%
+% Usage: |\ettl@nbk |\prm{string}\chcat/8\chcat/8\prm{true}\prm{false}\chcat/8\chcat/8
+% \begin{tabbing}
+% \qquad\=if \prm{string} is blank:¤\=\#1=\CH/,¤`\#2=\o,¤\#3=\prm{true},¤\=\#4=\prm{false}\\
+% \>\hfil otherwise:\>\#3=\CH/,\>\#4=\prm{true}¤(and \#5=\prm{false})
+%\end{tabbing}
+% \begin{macrocode}
+\long\def\ettl@nbk #1#2/#3#4#5//{#4}
+\long\def\ettl@nbk@else#1#2/#3#4#5//#6\else#7\fi{\fi#4}
+% \end{macrocode}
+% \end{Macro*}
+%
+%\begin{macro}{\ettl@ney}
+% \cs{ettl@ney}\FEII is exactly |\ifnotempty| but with the syntax of |\ettl@nbk|: it may be used in place of |\ettl@nbk|:
+% \begin{macrocode}
+\long\def\ettl@ney#1//#2#3//{\romannumeral 0\csname @%
+ \ifcat $\detokenize{#1}$first\else second\fi oftwo\endcsname
+ { #2}{ #3}}
+% \end{macrocode}
+%\end{macro}
+%
+% \iffalse
+%<package>
+%<package>% The following macros are not used (here just for memory, in case of...)
+% \fi
+%
+%\begin{macro}{\ettl@nbk@cat} \FE
+% \CSbf{ettl@nbk@cat} switches to \prm{true} if \prm{string} is not blank AND if its first token has the
+% same category code of \prm{tokenA}:
+%
+% Usage: |\ettl@nbkcat |\prm{tokenA}\prm{string}|//|\prm{same catcodes}\prm{different catcodes}|//|
+% \begin{macrocode}
+\long\def\ettl@nbk@cat#1#2#3/#4#5#6//{\ettl@nbk#6//%
+ {\ifcat#1#2\ettl@else#5\else\ettl@fi#6\fi}{#5}//}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\ettl@nbk@ifx} \FE
+% \CSbf{ettl@nbk@ifx} switches to \prm{true} if \prm{string} is not blank AND if its first token is
+% equal to \prm{tokenA} in the sense of \cs{ifx}:
+%
+% USAGE: |\ettl@nbk@ifx |\prm{tokenA}\prm{string}|//|\prm{true}\prm{false}|//|
+% \begin{macrocode}
+\long\def\ettl@nbk@ifx#1#2#3/#4#5#6//{\ettl@nbk#6//%
+ {\ifx#1#2\ettl@else#5\else\ettl@fi#6\fi}{#5}//}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\ettl@nbk@if} \FE
+% \CSbf{ettl@nbk@if} switches to \prm{true} if \prm{string} is not blank AND if its first token is
+% equal to \prm{tokenA} in the sense of \cs{if}:
+%
+% USAGE: |\ettl@nbk@if |\prm{tokenA}\prm{string}|//|\prm{true}\prm{false}|//|
+% \begin{macrocode}
+\long\def\ettl@nbk@if#1#2#3/#4#5#6//%
+ {\ettl@nbk#6//{\if#1#2\ettl@else#5\else\ettl@fi#6\fi}{#5}//}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\ettl@nbk@IF} \FE
+% More generally: |\ettl@nbk@IF[cat]|=|\ettl@nbk@ifcat|¤|\ettl@nbk@IF[x]|=|\ettl@nbk@ifx|¤|\ettl@nbk@IF[]|=|\ettl@nbk@if|:
+% \begin{macrocode}
+\long\def\ettl@nbk@IF[#1]#2#3#4/#5#6#7//{\ettl@nbk#7//%
+ {\csname if#1\endcsname\ettl@else#6\else\ettl@fi#7\fi}{#6}//}
+% \end{macrocode}
+%\end{macro}
+%
+%
+%\iffalse
+%<package>
+%<package>%% \@gobblespace and The Space Token
+% \fi
+%\begin{Macro}{@gobblespace}
+% \begin{macrocode}
+\long\def\@gobblespace#1 {#1}
+% \end{macrocode}
+%\end{Macro}
+%
+% \iffalse
+%<package>
+%<package>%% \@gobblescape \cs-token
+% \fi
+%
+% \begin{Macro}{@gobblescape}
+% This sequence of commands is very often used (even in \sty{latex.ltx}). So
+% it appears to be better to put it in a macro. It's aim is to reverse the
+% mechanism of |\csname|...|\endcsname|:
+% \begin{macrocode}
+\newcommand*\@gobblescape{\romannumeral-`\q\expandafter\@gobble\string}
+% \end{macrocode}
+% {\rmk May be we could do better, testing first if the next token is a control sequence...}
+% \end{Macro}
+%
+% \iffalse
+%<package>
+%<package>% The swap macros
+% \fi
+%
+%\begin{Macro}{@swap}
+% \CS{@swap} reverses the order and does not add any curly braces:
+% \begin{macrocode}
+\newcommand\@swap[2]{#2#1}
+\@swap{ }{\let\ettl@sptoken= }% This makes \ettl@sptoken a space token
+% \end{macrocode}
+%\end{Macro}
+%
+% \begin{Macro}{@swaparg}
+% \CS{@swaparg} reverses the order: the first argument (that will become the second), is
+% considered to be the first argument of the second (\textbf{!}):
+% \begin{macrocode}
+\newcommand\@swaparg[2]{#2{#1}}
+% \end{macrocode}
+% \end{Macro}
+%
+%\begin{Macro}{@swaplast}
+% \CS{@swaplast} reverse the order of two tokens, but keeps the first in first position:
+% \begin{macrocode}
+\newcommand\@swaplast[3]{#1#3#2}
+% \end{macrocode}
+%\end{Macro}
+%
+% \begin{Macro}{@swaptwo}
+% \CS{@swaptwo} reserves the order but keeps the curly braces:
+% \begin{macrocode}
+\newcommand\@swaptwo[2]{{#2}{#1}}
+% \end{macrocode}
+% {\rmk this macro is used in \cmdref{gettokslistindex}}
+% \end{Macro}
+%
+% \Subsection{Expansion control}
+%
+% \iffalse
+%<package>
+%<package>%% \expandaftercmds : expansion control
+%<package>% level 1 : \expandaftercmds { code }{ cs-token }
+%<package>% level 2 : \expandaftercmds\expandaftercmds { code }{ cs-token }
+% \fi
+%
+% \begin{Macro}{expandaftercmds}
+% \CSbf{expandaftercmds} generalizes \CSbf{expandafter}: arbitrarily \prm{code} might be
+% put as a first argument.
+%
+% The idea is to \textit{swap} the arguments in order to expand the second (in first position after the swap)
+% as many times as there are \cs{expandnext}s. At exit, swap again.
+% \begin{macrocode}
+\newcommand\expandaftercmds[2]{%
+ \ifsingletoken\expandaftercmds{#1}
+ {\expandafter@cmds{#2}{\expandafter\expandafter\expandafter}}
+ {\expandafter\@swap\expandafter{#2}{#1}}}
+\long\def\expandafter@cmds#1#2#3{%
+ \ifsingletoken\expandaftercmds{#1}
+ {\expandafter@cmds{#3}{\expandafter#2#2}}
+ {#2\@swap#2{#3}{#1}}}
+% \end{macrocode}
+% \end{Macro}
+%
+%
+% \begin{Macro}{expandnext}
+%
+% This code is not properly tricky but if you're eager to understand the job of each \cs{expandafter},
+% it's best to go straight at the log.
+%
+% \iffalse
+%<package>
+%<package>%% \expandnext : expansion control
+%<package>% level 1 : \expandnext { code }{ control sequences : the first is expanded before code }
+%<package>% level 2 : \expandnext\expandnext{ code }{ control sequences }
+% \fi
+% \begin{macrocode}
+\newcommand\expandnext[2]{%
+ \ifsingletoken\expandnext{#1}
+ {\@expandnext{#2}{\expandafter\expandafter\expandafter}}
+ {\expandafter\@swaparg\expandafter{#2}{#1}}}
+\long\def\@expandnext#1#2#3{%
+ \ifsingletoken\expandnext{#1}
+ {\@expandnext{#3}{\expandafter#2#2}}
+ {#2\@swaparg#2{#3}{#1}}}
+% \end{macrocode}
+% \end{Macro}
+%
+% \iffalse
+%<package>
+%<package>%% \expandnexttwo{ code }{ control sequences }{ control sequences }
+% \fi
+%
+%\begin{Macro}{expandnexttwo}
+\newcommand\expandnexttwo[3]{\expandnext{\expandnext{#1}{#2}}{#3}}
+%\end{Macro}
+%
+% \iffalse
+%<package>
+%<package>%% \ExpandAfter { code } { cs-token }
+% \fi
+%
+%\begin{Macro}{ExpandAftercmds}
+% \cs{ExpandAftercmds} acts like the primitive \cs{expandafter} but expands totally the second \textbfsf{token}:
+% \begin{macrocode}
+\newcommand\ExpandAftercmds[2]{\expandafter\@swap\expandafter{\romannumeral-`\q#2}{#1}}
+% \end{macrocode}
+%\end{Macro}
+%
+% \iffalse
+%<package>
+%<package>%% \ExpandNext { code } { argument }
+% \fi
+%
+% \begin{Macro}{ExpandNext}
+% \cs{romannumeral} forces the expansion of the second \textbfsf{argument.}
+% \begin{macrocode}
+ % I'm not sure it is interesting to use \expandnext here...
+ %\newcommand\ExpandNext[2]{\expandnext{#1}{\romannumeral-`\q#2}}
+\newcommand\ExpandNext[2]{\expandafter\@swaparg\expandafter{\romannumeral-`\q#2}{#1}}
+% \end{macrocode}
+% \end{Macro}
+%
+% \iffalse
+%<package>
+%<package>%% \ExpandNextTwo { code } { arg1 }{ arg2 }
+% \fi
+%
+%\begin{Macro}{ExpandNextTwo}
+% \begin{macrocode}
+\newcommand\ExpandNextTwo[3]{\ExpandNext{\ExpandNext{#1}{#2}}{#3}}
+% \end{macrocode}
+%\end{Macro}
+%
+% \iffalse
+%<package>
+%<package>% noexpandcs { csname }
+% \fi
+%
+% \begin{Macro}{noexpandcs}
+% {\rmk|\noexpandcs| may be abbreviated f.ex. in |\`#1`| or |\"#1"| in |\edef| that take place in a group.}
+% \begin{macrocode}
+\providecommand*\noexpandcs[1]{\expandafter\noexpand\csname #1\endcsname}
+% \end{macrocode}
+% \end{Macro}
+%
+% \iffalse
+%<package>
+%<package>% noexpandafter
+% \fi
+%
+% \begin{Macro}{noexpandafter}
+% {\rmk \cmd{noexpandafter} only means \cmd{noexpand}\cmd{expandafter} and is shorter to type.}
+% \begin{macrocode}
+\newcommand*\noexpandafter{\noexpand\expandafter}
+% \end{macrocode}
+%
+% \end{Macro}
+%
+% \Subsection{Meaning of control sequences}
+%
+% \iffalse
+%<package>
+%<package>%% \thefontname
+% \fi
+%
+%\begin{Macro}{thefontname}
+% \begin{macrocode}
+\newcommand\thefontname{\nfss@text{\expandafter\expandafter\expandafter\ettl@thefontname
+ \expandafter\expandafter\expandafter\meaning
+ \expandafter\the\expandafter\font
+ \expandafter\string\expandafter(%
+ \expandafter\string\the\font\string)}}
+\ifcsname T1/cmr/m/n/10\endcsname
+ \letcs\ettl@thefontname{T1/cmr/m/n/10}%
+\else
+ \font\ettl@thefontname=ecrm1000
+\fi
+% \end{macrocode}
+%\end{Macro}
+%
+% \iffalse
+%<package>
+%<package>%% \showcs { csname }
+% \fi
+%
+% \begin{Macro}{showcs}
+% \cs{showcs} shows the meaning of a named control sequence:
+% \begin{macrocode}
+\providecommand*\showcs[1]{\expandafter\show\csname#1\endcsname}
+% \end{macrocode}
+% \end{Macro}
+%
+% \iffalse
+%<package>
+%<package>%% \showthecs { csname }
+% \fi
+%
+%\begin{Macro}{showthecs}
+% \cs{showthecs} shows the value of the named register:
+% \begin{macrocode}
+\providecommand*\showthecs[1]{\expandafter\showthe\csname#1\endcsname}
+% \end{macrocode}
+%\end{Macro}
+%
+%
+% \iffalse
+%<package>
+%<package>%% \meaningcs { csname }
+% \fi
+%
+% \begin{Macro}{meaningcs}
+% \cs{meaningcs} expands in one level:
+% \begin{macrocode}
+\providecommand\meaningcs[1]{\romannumeral-`\q
+ \csname\ifcsdef{#1}{ettl@meaningcs\endcsname{#1}}
+ {meaning\endcsname\@undefined}}
+\def\ettl@meaningcs#1{\expandafter\meaning\csname#1\endcsname}% here we don't need \z@ to stop \romannumeral
+ % because \meaning is never blank nor begins with a space...
+% \end{macrocode}
+% \end{Macro}
+%
+% \iffalse
+%<package>
+%<package>%% \strip@meaning { cs-token }
+%<package>%% \strip@meaningcs { csname }
+% \fi
+%
+% \begin{Macro}{strip@meaning}
+% Just give the meaning without the prefix `|macro:|`. \cs{strip@prefix} will expand to an empty string if
+% its argument is undefined, and to the |\meaning| if it is not a macro.
+% \begin{Macro}{strip@meaningcs}
+% The same but for named control sequences:
+% \begin{macrocode}
+\newcommand*\strip@meaning[1]{\romannumeral\csname\ifdef{#1}%
+ {\ifdefmacro{#1}{ettl@strip@meaning}{ettl@meaning}\endcsname#1}{z@\endcsname}}
+\providecommand*\strip@meaningcs[1]{\romannumeral\csname\ifcsdef{#1}%
+ {\ifcsmacro{#1}{ettl@strip@meaning}{ettl@meaning}%
+ \expandafter\endcsname\csname#1\endcsname}
+ {z@\endcsname}}
+\def\ettl@strip@meaning{\expandafter\expandafter\expandafter\z@% for \romannumeral in case the \meaning is blank...
+ \expandafter\strip@prefix\meaning}
+\def\ettl@meaning{\expandafter\z@\meaning}
+% \end{macrocode}
+% \end{Macro}
+% \end{Macro}
+%
+% \iffalse
+%<package>
+%<package>%% \parameters@meaning { cs-token }
+%<package>%% \parameters@meaningcs { csname }
+% \fi
+%
+% \begin{Macro}{parameters@meaning}
+% \begin{Macro*}{parameters@meaningcs}
+% Expands to the \textit{parameter string} of a macro, or to an empty string if not a macro:
+% \begin{macrocode}
+\providecommand*\parameters@meaning[1]{}
+\edef\parameters@meaning#1{\unexpanded{\romannumeral\expandafter
+ \expandafter\expandafter\z@\expandafter\ettl@params@meaning%
+ \meaning}#1\detokenize{macro:->}/}
+\providecommand*\parameters@meaningcs[1]{}
+\edef\parameters@meaningcs#1{\unexpanded{\romannumeral\ettl@expandafthree\z@
+ \expandafter\expandafter\expandafter\ettl@params@meaning%
+ \expandafter\meaning\csname}#1\endcsname\detokenize{macro:->}/}
+\edef\ettl@params@meaning{%
+ \def\noexpand\ettl@params@meaning\detokenize{macro:}##1\detokenize{->}##2/{##1}%
+}\ettl@params@meaning
+% \end{macrocode}
+% \end{Macro*}
+% \end{Macro}
+%
+% \iffalse
+%<package>
+%<package>%% \ifdefcount { cs-token }{ true }{ false } \FEII
+%<package>%% \ifdefdimen { cs-token }{ true }{ false } \FEII
+%<package>%% \ifdeftoks { cs-token }{ true }{ false } \FEII
+%<package>%% \ifdefskip { cs-token }{ true }{ false } \FEII
+%<package>%% \ifdefmuskip { cs-token }{ true }{ false } \FEII
+%<package>%% \ifdefchar { cs-token }{ true }{ false } \FEII
+%<package>%% \ifdefmathchar { cs-token }{ true }{ false } \FEII
+% \fi
+%
+%\begin{Macro*}{ifdefcount}
+%\begin{Macro*}{ifdeftoks}
+%\begin{Macro*}{ifdefdimen}
+%\begin{Macro*}{ifdefskip}
+%\begin{Macro*}{ifdefmuskip}
+%\begin{Macro*}{ifdefchar}
+%\begin{Macro*}{ifdefmathchar}
+%\begin{Macro*}{ifdefblankspace}
+%\begin{Macro*}{ifdefthechar}
+%\begin{Macro}[ifdefcount]{ifdeftheletter}
+% \cs{ettl@ifdef} will defined those five macros (and be undefined itself at the end):
+% \begin{macrocode}
+\def\ettl@ifdef[#1]{\expandafter\ettl@ifd@f\expandafter{#1}}
+\def\ettl@ifd@f#1#2{%
+ \csdef{ettl@ifdef#2}##1#1##2/End§Meaning/{\ettl@nbk##2//\rmn@firstoftwo\rmn@secondoftwo//}
+ \csedef{ifdef#2}##1{\noexpand\romannumeral\noexpandafter%
+ \noexpandcs{ettl@ifdef#2}\noexpand\meaning##1#1/End§Meaning/}%//{##2}{##3}//}
+}
+\ettl@ifdef[\string\count]{count} % defines \def\ifdefcount
+\ettl@ifdef[\string\toks]{toks} % \def\ifdeftoks
+\ettl@ifdef[\string\dimen]{dimen} % \def\ifdefdimen
+\ettl@ifdef[\string\skip]{skip} % \def\ifdefskip
+\ettl@ifdef[\string\muskip]{muskip} % \def\ifdefmuskip
+\ettl@ifdef[\string\char]{char} % \def\ifdefchar
+\ettl@ifdef[\string\mathchar]{mathchar} % \def\ifdefmathchar
+\ettl@ifdef[\detokenize{blank space}]{blankspace}% \def\ifdefblankspace
+\ettl@ifdef[\detokenize{the character}]{thechar}% \def\ifdefthechar
+\ettl@ifdef[\detokenize{the letter}]{theletter} % \def\ifdeftheletter
+\undef\ettl@ifdef\undef\ettl@ifd@f
+% \end{macrocode}
+%\end{Macro}
+%\end{Macro*}
+%\end{Macro*}
+%\end{Macro*}
+%\end{Macro*}
+%\end{Macro*}
+%\end{Macro*}
+%\end{Macro*}
+%\end{Macro*}
+%\end{Macro*}
+%
+% \iffalse
+%<package>
+%<package>%% \avoidvoid [ replacement code ]{ cs-token / string }
+%<package>%% \avoidvoid*[ replacement code ]{ cs-token / string }
+% \fi
+% \begin{Macro*}{avoidvoid}
+% \begin{Macro}{avoidvoid*}
+% \cs{avoivoid}\oprm{replacement code}\prm{cs-token} will expand the optional parameter (default: an empty string) if the mandatory argument is void (\ie
+% is either undefined, a token whose meaning is |\relax|, a parameterless macro whose replacement text is empty).
+% Otherwise, it will expand its mandatory argument (\prm{cs-token}):
+% \begin{macrocode}
+\newcommand\avoidvoid[1]{\romannumeral\FE@ifstar{#1}
+ {\ettl@voidvoid{\ettl@ifdefempty\ifempty}}
+ {\ettl@voidvoid{\ettl@ifdefvoid\ifblank}}}
+\long\def\ettl@voidvoid#1#2{\FE@testopt{#2}{\ettl@voidv@id#1}{}}
+\long\def\ettl@voidv@id#1#2[#3]#4{\ifiscs{#4}{#1{#4}}{#2{#4}}{\z@#3}{\z@#4}}
+% \end{macrocode}
+% and the helper macros:
+% \begin{macrocode}
+\long\def\ettl@ifdefvoid#1{\csname @\ifx#1\relax first%
+ \else\expandafter\expandafter\expandafter\ettl@nbk\strip@meaning#1//{second}{first}//%
+ \fi oftwo\endcsname}
+\long\def\ettl@ifdefempty#1{\expandafter\expandafter\expandafter\ifempty%
+ \expandafter\expandafter\expandafter{\strip@meaning#1}}
+% \end{macrocode}
+%\end{Macro}
+%\end{Macro*}
+%
+% \iffalse
+%<package>
+%<package>%% \avoidvoidcs [ replacement code ]{ cs-name }
+%<package>%% \avoidvoidcs*[ replacement code ]{ cs-name }
+% \fi
+%
+%\begin{Macro*}{avoidvoidcs}
+%\begin{Macro}{avoidvoidcs*}
+% \cs{avoidvoidcs} does the same as \cs{avoidvoid} but the mandatory argument \prm{cs-name} is interpreted
+% as a control sequence name. Therefore, you cannot test a |string| with \cs{avoidvoidcs}.
+%
+% \cs{avoidcsvoid} is an alias (for |neu-neu|...):
+% \begin{macrocode}
+\newcommand\avoidvoidcs[1]{\romannumeral\FE@ifstar{#1}
+ {\ettl@avoidvoidcs{\ettl@ifdefempty}}
+ {\ettl@avoidvoidcs{\ettl@ifdefvoid}}}
+\long\def\ettl@avoidvoidcs#1#2{\FE@testopt{#2}{\ettl@@voidvoidcs#1}{}}
+\long\def\ettl@@voidvoidcs#1[#2]#3{\csname @\ifcsname#3\endcsname
+ \expandafter#1\csname#3\endcsname{first}{second}\else first\fi
+ oftwo\endcsname{\z@#2}{\z@\csname#3\endcsname}}
+% \end{macrocode}
+%\end{Macro}
+%\end{Macro*}
+%
+% \Subsection{Single tokens / single characters}
+%
+% \iffalse
+%<package>
+%<package>%% The ifx-test and the character-test
+% \fi
+%
+% \begin{Macro*}{ettl@ifx} \FE
+% \cs{ettl@ifx} is the \emph{equality-test macro} for \cmdref={character-test}{\cs{ifx} test}. In is designed to be used
+% inside |\csname|...|\endcsname| like:§
+% ¤¤|\ettl@ifx|\prm{tokenA}\prm{tokenB}{first}{second}:
+% \begin{macrocode}
+\long\def\ettl@ifx#1#2{\csname ettl@\ifx#1#21\else2\fi of2\endcsname}
+% \end{macrocode}
+% \end{Macro*}
+%
+%\begin{Macro*}{ettl@ifchar} \FE
+% \cs{ettl@ifchar} is the \emph{equality-test macro} for \cmdref={character-test}. It is designed to be in place of \cs{ettl@ifx}:
+% \begin{macrocode}
+\long\def\ettl@ifchar#1#2{\csname ettl@\if\noexpand#2\string#11of2\ettl@csname\fi
+ \unless\ifcat\noexpand#1\noexpand#22of2\ettl@csname\fi
+ \ifx#1#21\else2\fi of2\endcsname}
+% \end{macrocode}
+%\end{Macro*}
+%
+% \iffalse
+%<package>
+%<package>%% \ifsingletoken{ tokenA }{ tokenB }{ true }{ false }
+% \fi
+%
+%\begin{Macro}{ifsingletoken}
+% \cs{ifsingletoken} is a safe \cs{ifx}-test:
+% \begin{macrocode}
+\newcommand\ifsingletoken[2]{\romannumeral\csname rmn@\ettl@firstspace{#2}
+ {\ettl@nbk#1#2//{second}{\ifcat $\detokenize{#1#2}$first\else\ifx#1#2first\else second\fi\fi}//}
+ {\ifcat $\detokenize\expandafter{\ettl@cdr#2\@nil}$%
+ \expandafter\ettl@ifxsingle
+ \else\expandafter\ettl@carcar
+ \fi{#1}{#2}{first}{second}}%
+ oftwo\endcsname}
+\def\ettl@ifxsingle#1#2#3#4{\ettl@nbk#1//{\ifx#1#2#3\else#4\fi}{#4}//}
+% \end{macrocode}
+%\end{Macro}
+%
+% \iffalse
+%<package>
+%<package>%% \iffirsttoken token { string }{ true }{ false }
+% \fi
+%\begin{Macro}{iffirsttoken}
+% \cs{iffirsttoken} tests if \#1 and \#2 begins with the same token (the \cs{ifx}-test is used):
+% \begin{macrocode}
+\providecommand\iffirsttoken[2]{\romannumeral\csname rmn@%
+ \ettl@nbk#2//%
+ {\ettl@nbk#1//%
+ {\expandnexttwo\ettl@ifx{\ettl@car#2\@nil}{\ettl@car#1\@nil}{first}{second}}
+ {\ifcat $\detokenize{#1}$secondoftwo\ettl@csname\fi
+ \ettl@firstspace{#2}{first}{second}}//}%
+ {\ettl@nbk#1//%
+ {\ifcat $\detokenize{#2}$secondoftwo\ettl@csname\fi
+ \ettl@firstspace{#1}{first}{second}}
+ {\ifcat $\detokenize{#1#2}$first\else second\fi}}//%
+ oftwo\endcsname}
+% \end{macrocode}
+%\end{Macro}
+%
+% \iffalse
+%<package>
+%<package>%% \ifOneToken{ token }{ true }{ false }
+% \fi
+%
+% \begin{Macro}{ifOneToken}
+% \cs{ifOneToken} test if its argument contains only one token (possibly a space token):
+% \begin{macrocode}
+\newcommand\ifOneToken[1]{\romannumeral\csname rmn@\ettl@firstspace{#1}
+ {\ettl@nbk#1//{second}{\ifcat $\detokenize{#1}$second\else first\fi}//}
+ {\ifcat $\detokenize\expandafter{\ettl@cdr#1\@nil}$%
+ first\else second\fi}oftwo\endcsname}
+% \end{macrocode}
+% \end{Macro}
+%
+% \iffalse
+%<package>
+%<package>%% \ifsinglechar character{ string }{ true }{ false }
+% \fi
+%
+% \begin{Macro}{ifsinglechar}
+% Test if \#2 is a single character equal to \#1:
+% \begin{macrocode}
+\long\def\ifsinglechar#1#2{\romannumeral\csname rmn@\ettl@firstspace{#2}
+ {\ettl@nbk#2//{second}{\ifcat $\detokenize{#1#2}$first\else\ifx#1#2first\else second\fi\fi}//}
+ {\ifcat $\detokenize\expandafter{\ettl@cdr#2\@nil}$%
+ \expandafter\ettl@ifchar
+ \else\expandafter\ettl@carcar
+ \fi{#1}{#2}{first}{second}}%
+ oftwo\endcsname}
+% \end{macrocode}
+% \end{Macro}
+%
+% \iffalse
+%<package>
+%<package>%% \ifOneChar{ string }{ true }{ false }
+% \fi
+%
+% \begin{Macro}{ifOneChar}
+% \cs{ifOneChar}\prm{string}\prm{true}\prm{false}¤ detokenizes \prm{string} first (see also \cmdref*{ifOneToken}):
+% \begin{macrocode}
+\ettl@ifdefined\pdfmatch
+\newcommand\ifOneChar[1]{\romannumeral\csname rmn@%
+ \ifnum\pdfmatch{\detokenize{^.$}}{\detokenize{#1}}=1 first\else second\fi
+ oftwo\endcsname}
+\else
+\newcommand\ifOneChar[1]{\romannumeral\csname rmn@\ettl@firstspace{#1}
+ {\ettl@nbk#1//{second}{\ifcat $\detokenize{#1}$second\else first\fi}//}
+ {\ifcat $\expandafter\ettl@cdr\detokenize{#1}\@nil$%
+ first\else second\fi}oftwo\endcsname}
+\fi%\pdfmatch
+% \end{macrocode}
+% \end{Macro}
+%
+% \iffalse
+%<package>
+%<package>%% \ifOneCharWithBlanks{ string }{ true }{ false }
+% \fi
+%
+%\begin{Macro}{ifOneCharWithBlanks}
+% \begin{macrocode}
+\ettl@ifdefined\pdfmatch
+\newcommand\ifOneCharWithBlanks[1]{\romannumeral\csname rmn@%
+ \ifnum\pdfmatch{\detokenize{^[[:space:]]*[^[:space:]][[:space:]]*$}}{\detokenize{#1}}=1 %
+ first\else second\fi oftwo\endcsname}
+\else
+\newcommand\ifOneCharWithBlanks[1]{\romannumeral\csname rmn@\ettl@nbk#1//%
+ {\expandafter\expandafter\expandafter\ettl@nbk
+ \expandafter\ettl@cdr\detokenize{#1}\@nil//{second}{first}//}%
+ {second}//oftwo\endcsname}
+\fi
+% \end{macrocode}
+%\end{Macro}
+%
+% \iffalse
+%<package>
+%<package>%% \iffirstchar{ string1 }{ string2 }{ true }{ false }
+% \fi
+%
+% \begin{Macro}{iffirstchar}
+% |\iffirstchar| test if \#1 and \#2 begins with the same character or token (the \cmdref={character-test} is used):
+% \begin{macrocode}
+\newcommand\iffirstchar[2]{\romannumeral\csname rmn@%
+ \ettl@nbk#2//%
+ {\ettl@nbk#1//%
+ {\expandnexttwo\ettl@ifchar{\ettl@car#2\@nil}{\ettl@car#1\@nil}{first}{second}}
+ {\ifcat $\detokenize{#1}$secondoftwo\ettl@csname\fi
+ \ettl@firstspace{#2}{first}{second}}//}%
+ {\ettl@nbk#1//%
+ {\ifcat $\detokenize{#2}$secondoftwo\ettl@csname\fi
+ \ettl@firstspace{#1}{first}{second}}
+ {\ifcat $\detokenize{#1#2}$first\else second\fi}}//%
+ oftwo\endcsname}
+% \end{macrocode}
+% \end{Macro}
+%
+% \iffalse
+%<package>
+%<package>%% \ifiscs { string }{ true }{ false }
+% \fi
+%
+%\begin{Macro}{ifiscs}
+% \cs{ifiscs}\prm{string} expands \prm{true} only if \prm{string} is a single control-word:
+% \begin{macrocode}
+\newcommand\ifiscs[1]{\romannumeral\csname rmn@\ettl@nbk#1//%
+ {\ifcat $\expandafter\ettl@cdr\detokenize{#1}\@nil$secondoftwo\ettl@csname\fi
+ \ifcat $\detokenize\expandafter{\ettl@cdr#1\@nil}$%
+ \expandafter\ettl@firstspace
+ \else secondoftwo\ettl@csname\fi{#1}{second}{first}}
+ {second}//oftwo\endcsname}
+% \end{macrocode}
+%\end{Macro}
+%
+% \iffalse
+%<package>
+%<package>%% \detokenizeChars { list of single tokens }
+% \fi
+%
+%\begin{Macro}{detokenizeChars}
+% \cs{detokenizeChars} selectively detokenizes the tokens of the \cmdref={list of single tokens}: single characters are
+% detokenized while control sequences remain the same:
+% \begin{macrocode}
+\newcommand\detokenizeChars[1]{\expandafter\ettl@dosinglelist
+ \expandafter\ettl@do@detokenChars\expandafter{\romannumeral\protectspace{\z@#1}}}
+\long\def\ettl@do@detokenChars#1{\ifOneChar{#1}\detokenize\unexpanded{#1}}
+% \end{macrocode}
+%\end{Macro}
+%
+% \iffalse
+%<package>
+%<package>%% \protectspace { string }
+% \fi
+%
+%\begin{Macro}{protectspace}
+% \cs{protectspace} puts curly braces (group characters) around spaces in the string given as argument.
+% This is useful for loops into lists (\cs{listloop}, \cs{csvloop}...). \cs{protectspace} is an exemple
+% of a loop which is 2-purely expandable:
+% \begin{macrocode}
+\newcommand\protectspace[1]{\romannumeral\ettl@protectspace#1 /End§String/}
+\long\def\ettl@protectspace#1 #2/End§String/{\ifempty{#2}{\z@#1}
+ {\expandafter\@swap\expandafter{\romannumeral\ettl@protectspace#2/End§String/}{\z@#1{ }}}}
+% \end{macrocode}
+%\end{Macro}
+%
+% \Subsection{Character and Strings}
+%
+% \iffalse
+%<package>
+%<package>%% \ifempty{ text }{ true }{ false }
+% \fi
+%
+% \begin{Macro}{ifempty}
+% |\ifempty| is based on |\detokenize| and can manage with any argument.
+% \begin{macrocode}
+\newcommand\ifempty[1]{\romannumeral\csname rmn@\ifcat $\detokenize{#1}$%
+ first\else second\fi oftwo\endcsname}
+% \end{macrocode}
+% \end{Macro}
+%
+% \iffalse
+%<package>
+%<package>%% \ifnotempty{ text }{ true }{ false }
+% \fi
+%
+% \begin{Macro}{ifnotempty}
+% |\ifnotempty| is based on |\detokenize| and can manage with any argument.
+% \begin{macrocode}
+\newcommand\ifnotempty[1]{\romannumeral\csname rmn@\ifcat $\detokenize{#1}$%
+ second\else first\fi oftwo\endcsname}
+% \end{macrocode}
+% \end{Macro}
+%
+% \iffalse
+%<package>
+%<package>%% \xifempty{ text }{ true }{ false }
+% \fi
+% \begin{Macro}{xifempty}
+% |\xifempty| is based on pdf-TeX{} |\pdfstrcmp| and work with any argument.
+% \begin{macrocode}
+\newcommand\xifempty[1]{\xifstrcmp{#1}{}}
+\ettl@onlypdfTeX\pdfstrcmp\xifempty[\xifstrempty]
+% \end{macrocode}
+% \end{Macro}
+%
+% \iffalse
+%<package>
+%<package>%% \ifnotblank{ text }{ true }{ false }
+% \fi
+%
+% \begin{Macro}{ifnotblank}
+% \cs{ifnotblank} \CS{ifnotblank} |\ifnotblank| \CSbf{ifnotblank} \textvb{ifnotblank} reverses the test of \cs{ifblank}.
+%
+% {\usefont{T1}{pcr}{m}{n}ifnotblank}{\usefont{T1}{txtt}{m}{n}ifnotblank}
+% \begin{macrocode}
+\long\def\ifnotblank#1#2#3{\ettl@nbk#1//{#2}{#3}//}
+% \end{macrocode}
+% \end{Macro}
+%
+% \iffalse
+%<package>
+%<package>%% \xifblank{ string }{ true }{ false }
+% \fi
+%
+% \begin{Macro}{xifblank}
+% Just expands the parameter using |\protected@edef| before testing for |\ifblank|:
+% \begin{macrocode}
+\newrobustcmd\xifblank[1]{\begingroup
+ \protected@edef\@xifblank{\endgroup
+ \noexpand\ifblank{#1}%
+ }\@xifblank}
+% \end{macrocode}
+% \end{Macro}
+%
+% \iffalse
+%<package>
+%<package>%% \deblank{ string }
+% \fi
+% \begin{Macro}{deblank}
+% From a code in \xpackage{environ.sty}.
+% \begin{macrocode}
+\newcommand\deblank[1]{\romannumeral\ettl@deblank#1/ /}
+\long\def\ettl@deblank#1 /{\ettl@deblank@i#1/}
+\long\def\ettl@deblank@i#1/#2{\z@#1}
+% \end{macrocode}
+% \end{Macro}
+%
+%
+%\begin{Macro*}{ettl@stringify} \FE
+% \cs{ettl@stringify} is used in the definition of \cs{ettl@safe@ifx}:
+% \begin{macrocode}
+\newcommand\ettl@stringify[1]{\romannumeral-`\q\ettl@expandafthree\@gobblescape%
+ \expandafter\ettl@deblank\detokenize{#1}/ /}
+% \end{macrocode}
+%\end{Macro*}
+%
+%
+% \iffalse
+%<package>
+%<package>%% \ifstrcmp{ string1 }{ string2 }{ true }{ false }
+% \fi
+%
+% \begin{Macro}{ifstrcmp}
+% The macro is based on the |\pdfstrcmp| primitive if it is available.
+% Otherwise, \cs{ifstrcmp} is the same as \xpackage{etoolbox}-\cs{ifstrequal}.
+% \begin{macrocode}
+\newcommand\ifstrcmp[2]{\romannumeral\csname rmn@%
+ \ifnum\pdfstrcmp{\detokenize{#1}}{\detokenize{#2}}=0 first\else second\fi
+ oftwo\endcsname}
+\ettl@onlypdfTeX\pdfstrcmp\ifstrcmp[\ifstrequal]
+% \end{macrocode}
+% \end{Macro}
+%
+% \iffalse
+%<package>
+%<package>%% \xifstrcmp{ string1 }{ string2 }{ true }{ false }
+% \fi
+%
+% \begin{Macro}{xifstrcmp}
+% The macro is based on the |\pdfstrcmp| primitive.
+% \begin{macrocode}
+\newcommand\xifstrcmp[2]{\csname @%
+ \ifnum\pdfstrcmp{#1}{#2}=0 first\else second\fi
+ oftwo\endcsname}
+\ettl@onlypdfTeX\pdfstrcmp\xifstrcmp[\xifstrequal]
+% \end{macrocode}
+% \end{Macro}
+%
+% \begin{Macro}{xifstrequal}
+% The macro is based on \xpackage{etoolbox}-|\ifstrequal|.
+% \begin{macrocode}
+\newrobustcmd\xifstrequal[2]{\begingroup
+ \protected@edef\@xifstrequal{\endgroup\noexpand\ifstrequal{#1}{#2}%
+ }\@xifstrequal}
+% \end{macrocode}
+% \end{Macro}
+%
+% \iffalse
+%<package>
+%<package>%% \ifcharupper{ string }{ true }{ false }
+%<package>%% \ifcharlower{ string }{ true }{ false }
+% \fi
+%
+% \begin{Macro*}{ifcharupper}
+% Test if the character code equals to its upper case code:
+% \begin{Macro}{ifcharlower}
+% Test if the character code equals to its lower case code:
+% \begin{macrocode}
+\newcommand\ifcharupper[1]{\romannumeral\csname rmn@%
+ \ifnum`\#1=\uccode`\#1 first\else second\fi oftwo\endcsname}
+\newcommand\ifcharlower[1]{\romannumeral\csname rmn@%
+ \ifnum`\#1=\lccode`\#1 first\else second\fi oftwo\endcsname}
+% \end{macrocode}
+% \end{Macro}
+% \end{Macro*}
+%
+% \iffalse
+%<package>
+%<package>%% \ifuppercase{ string }{ true }{ false }
+%<package>%% \iflowercase{ string }{ true }{ false }
+% \fi
+% \begin{Macro}{ifuppercase}
+% Compares the |\uppercase| transformation of a string with itself:
+% \begin{macrocode}
+\newrobustcmd\ifuppercase[1]{\uppercase{\ifstrcmp{#1}}{#1}}
+% \end{macrocode}
+% \end{Macro}
+%
+% \begin{Macro}{iflowercase}
+% Compares the |\lowercase| transformation of a string with itself:
+% \begin{macrocode}
+\newrobustcmd\iflowercase[1]{\lowercase{\ifstrcmp{#1}}{#1}}
+% \end{macrocode}
+% \end{Macro}
+%
+%
+% \iffalse
+%<package>
+%<package>%% \ifstrmatch{ pattern }{ string }{ true }{ false }
+% \fi
+%
+% \begin{Macro}{ifstrmatch}
+% The macro is base on the |\pdfmatch| primitive.
+% \begin{macrocode}
+\newcommand\ifstrmatch[2]{\romannumeral\csname rmn@%
+ \ifnum\pdfmatch{#1}{#2}=1 first\else second\fi oftwo\endcsname}
+\ettl@onlypdfTeX\pdfmatch\ifstrmatch
+% \end{macrocode}
+% \end{Macro}
+%
+% \iffalse
+%<package>
+%<package>%% \ifstrdigit{ string }{ true }{ false }
+% \fi
+%
+%\begin{Macro}{ifstrdigit}
+% \cs{ifstrdigit} expands \prm{true} if \prm{string} is a single digit (without spaces):
+% \begin{macrocode}
+\ettl@ifdefined\pdfmatch
+\newcommand\ifstrdigit[1]{\romannumeral\csname rmn@\ifnum\pdfmatch{\detokenize{^[[:digit:]]$}}%
+ {\detokenize{#1}}=1 first\else second\fi oftwo\endcsname}
+\else
+\def\do#1{\cslet{ettl@number#1}=#1%
+}\docsvlist{0,1,2,3,4,5,6,7,8,9}
+\newcommand\ifstrdigit[1]{\romannumeral\csname rmn@%
+ \ifcsname ettl@number\detokenize{#1}\endcsname first\else second\fi oftwo\endcsname}
+\fi%\pdfmatch
+% \end{macrocode}
+%\end{Macro}
+%
+% \iffalse
+%<package>
+%<package>%% \ifstrnum{ string }{ true }{ false }
+% \fi
+%
+%\begin{Macro}{ifstrnum}
+% \cs{ifstrnum} expands \prm{true} if \prm{string} is a number (integer) in the sense of \eTeX:
+% \begin{macrocode}
+\ettl@ifdefined\pdfmatch
+\newcommand\ifstrnum[1]{\romannumeral\csname rmn@\ifnum\pdfmatch
+ {\detokenize{^([[:space:]]*-?)*+[[:digit:]]+[[:space:]]*$}}{\detokenize{#1}}=1 %
+ first\else second\fi oftwo\endcsname}
+\else
+\newcommand\ifstrnum[1]{\romannumeral\csname rmn@\ettl@nbk#1//%
+ {\expandafter\ettl@numberminus\detokenize{#1}-/End§String/}{second}//oftwo\endcsname}
+\long\def\ettl@numberminus#1-#2/End§String/{\ettl@nbk#2//%
+ {\ettl@nbk#1//{second}{\ettl@numberminus#2/End§String/}//}%
+ {\expandafter\expandafter\expandafter\ettl@numberspace\deblank{#1} /End§String/}//}%
+\long\def\ettl@numberspace#1 #2/End§String/{\ettl@nbk#2//{second}{\ettl@ifstrnum#1/End§String/}//}
+\long\def\ettl@ifstrnum#1#2/End§String/{%
+ \ifcsname ettl@number#1\endcsname% #1 detokenized before, ok
+ \ettl@nbk#2//{\ettl@ifstrnum#2/End§String/}{first}//%
+ \else second%
+ \fi}
+\fi%\pdfmatch
+% \end{macrocode}
+%\end{Macro}
+%
+% \iffalse
+%<package>
+%<package>%% \DeclareStringFilter[\global]{ \StringFilterMacro }{ string }
+% \fi
+%
+%\begin{Macro}{DeclareStringFilter}
+% \csbf{DeclareStringFilter} is the general contructor for purely expandable
+% \textbfsf{string-filter} macros:
+% \begin{macrocode}
+\newrobustcmd\DeclareStringFilter[3][\global]{\@ifdefinable#2%
+ {\expandnext\ettl@declarestrfilter%
+ {\csname\@gobblescape#2\detokenize{->"#3"}\endcsname}{#1}{#2}{#3}}}
+\newcommand\ettl@declarestrfilter[4]{%
+ #2\csdef{\@gobblescape#1}##1#4##2/End§String/{##1/##2}% This the FILTER
+ #2\long\def#3##1{\FE@modifiers{=<>?-+!}{##1}
+ {\ettl@strfilt@mod 0{{#4}{}{#1}[1]}}%=
+ {\ettl@strfilt@mod 1{{#4}{}{#1}[1]}}%<
+ {\ettl@strfilt@mod 2{{#4}{}{#1}[\ettl@intmax]}}%>
+ {\ettl@strfilt@mod 3{{#4}{}{#1}}}%?
+ {\ettl@strfilt@mod 4{{#4}{}{#1}}}%-
+ {\ettl@strfilt@mod 5{{#4}{}{#1}}}%+
+ {\ettl@strfilt\ettl@strfilt@count{#4}{}{#1}[\ettl@intmax]}%!
+ {\ettl@strfilt\ettl@strfilt@equal{#4}{}{#1}[1]}}}% default
+% \end{macrocode}
+%\end{Macro}
+%
+%\begin{macro}{\ettl@strfilt@mod} \FE
+% \cs{ettl@strfilt@mod} test the possible second modifier and choose the right macro to expand with
+% the right arguments:
+% \begin{macrocode}
+\def\ettl@strfilt@mod #1#2#3{%
+ \ifcase#1 \ettl@or\ettl@ifchardot{#3}%
+ {\ettl@strfilt\ettl@strfilt@equal#2}
+ {\FE@ifcharequal{#3}%
+ {\ettl@strfilt\ettl@strfilt@equaleq#2}%
+ {\ettl@strfilt\ettl@strfilt@equal#2}}%
+ \or\ettl@or\ettl@ifchardot{#3}%
+ {\ettl@strfilt\ettl@strfilt@start#2}%
+ {\FE@ifcharequal{#3}
+ {\ettl@strfilt\ettl@strfilt@starteq#2}%
+ {\ettl@strfilt\ettl@strfilt@start#2}}%
+ \or\ettl@or\ettl@ifchardot{#3}%
+ {\ettl@strfilt\ettl@strfilt@endby#2}%
+ {\FE@ifcharequal{#3}
+ {\ettl@strfilt\ettl@strfilt@endbyeq#2}%
+ {\ettl@strfilt\ettl@strfilt@endby#2}}%
+ \or\ettl@or\ettl@ifchardot{#3}%
+ {\ettl@strfilt\ettl@strfilt@instr#2[1]}
+ {\FE@testopt{#3}{\ettl@strfilt\ettl@strfilt@instr#2}{1}}%
+ \or\ettl@or\ettl@ifchardot{#3}%
+ {\ettl@strfilt@REMOVE{#2}[\ettl@intmax]}%
+ {\FE@testopt{#3}{\ettl@strfilt@REMOVE{#2}}{\ettl@intmax}}%
+ \or\ettl@fi\ettl@ifchardot{#3}%
+ {\ettl@strfilt@REPLACE#2[\ettl@intmax]}%
+ {\FE@testopt{#3}{\ettl@strfilt@REPLACE#2}{\ettl@intmax}}%
+ \fi}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\ettl@strfilt} \FE
+% \cs{ettl@strfilt} is the common start for the loop:
+% \begin{macrocode}
+\long\def\ettl@strfilt#1#2#3#4[#5]#6{% % #1 = test macro
+% #2 = substr
+% #3 = replacement
+% #4 = filter macro
+% #5 = number of times
+% #6 = user-given string
+ \ExpandAftercmds#1{\ettl@Remove #6/End§String/{#2}{#3}[{#5}]{#4}}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\ettl@strfilt@REMOVE} \FE
+% \cs{ettl@strfilt@REMOVE} is a pre-stage just before the common \cs{ettl@strfilt}:
+% \begin{macrocode}
+\long\def\ettl@strfilt@REMOVE #1[#2]{%
+% #1 = arguments for \ettl@strfilt
+% #2 = number of times
+ \ifnum\numexpr#2>0 \ettl@else\ettl@strfilt\ettl@strfilt@remove#1[#2]%
+ \else\expandafter\@firstofone%
+ \fi}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\ettl@strfilt@REPLACE} \FE
+% \cs{ettl@strfilt@REPLACE} is a pre-stage just before the common \cs{ettl@strfilt}:
+% \begin{macrocode}
+\long\def\ettl@strfilt@REPLACE #1#2#3#4[#5]#6#7{%
+ \ifnum\numexpr#5>0 \ettl@else\ettl@strfilt\ettl@strfilt@replace{#1}{#7}{#3}[{#5}]{#6}%
+ \else\expandafter\@firstoftwo%
+ \fi}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\ettl@Remove} \FE
+% \cs{ettl@Remove} applies the filter (\#5) and give the result to \cs{ettl@Remove@loop}:
+% \begin{macrocode}
+\long\def\ettl@Remove#1/End§String/#2#3[#4]#5{%
+% #1 = string or list
+% #2 = substring or item to remove
+% #3 = REPLACEMENT
+% #4 = number of times to remove
+% #5 = filter macro
+ \expandafter\ettl@Remove@loop #5#1//#2/End§String//End§String/{#3}[{#4-1}]{#5}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\ettl@Remove@loop} \FE
+% \cs{ettl@Remove@loop} is entitled to break the loop:
+% \begin{macrocode}
+\long\def\ettl@Remove@loop#1/#2//#3/End§String/#4[#5]#6{%
+% #1 = str before filter
+% #2 = str after filter
+% #3 = substr to remove
+% #4 = REPLACEMENT
+% #5 = iterindex
+% #6 = filter macro
+ \ifnum\numexpr#5>0 \ettl@nbk@else#2//%
+ {\ettl@Remove #1#4#2/End§String/{#3}{#4}[{#5}]{#6}}
+ {{#1}{#4#2}{#3}{#5}}//%
+ \else\ettl@fi{#1}{#4#2}{#3}{#5}%
+ \fi}
+% \end{macrocode}
+%\end{macro}
+%
+% \begin{macro}{test and result macros} \FE
+% Those macros are expanded after the end of the loop: they give the final expected result
+% from the four registers avaiblable at the end of the loop:
+% \begin{macrocode}
+\long\def\ettl@strfilt@equal #1#2#3#4{\csname @%
+ \ettl@nbk#3//{\ettl@nbk#1#2//{second}{first}//}{second}//oftwo\endcsname}
+\long\def\ettl@strfilt@equaleq #1#2#3#4{\csname @%
+ \ettl@nbk#3//{\ifnotempty{#1#2}{second}{first}}{second}//oftwo\endcsname}
+\long\def\ettl@strfilt@start #1#2#3#4{\csname @%
+ \ettl@nbk#1//{second}{first}//oftwo\endcsname}
+\long\def\ettl@strfilt@starteq #1#2#3#4{\csname @%
+ \ifnotempty{#1}{second}{first}oftwo\endcsname}
+\long\def\ettl@strfilt@endby #1#2#3#4{\csname @%
+ \ettl@nbk#3//{first}{second}//oftwo\endcsname}
+\long\def\ettl@strfilt@endbyeq #1#2#3#4{\csname @%
+ \ettl@nbk#3//{\ifempty{#2}{first}{second}}{second}//oftwo\endcsname}
+\long\def\ettl@strfilt@count #1#2#3#4{\number\numexpr\ettl@intmax-(#4)-\ettl@nbk#3//01//}
+\long\def\ettl@strfilt@instr #1#2#3#4{\csname @%
+ \ifnum\numexpr#4>0 second%
+ \else\ifnum\numexpr#4<0 first%
+ \else\ettl@nbk#3//{first}{second}//%
+ \fi\fi oftwo\endcsname}
+\long\def\ettl@strfilt@remove #1#2#3#4{#1#2}
+\long\def\ettl@strfilt@replace #1#2#3#4{#1\ettl@nbk#3//{#2}{}//}
+% \end{macrocode}
+% \end{macro}
+%
+% \Subsection{Purely expandable macros with options}
+%
+% \iffalse
+%<package>%----------------------------------------------------------------------------
+%<package>% Purely Expandable Macros With Options / Star Forms / Variants
+%<package>%% \FE@testopt{ #1 }{ commands }{ default option }
+% \fi
+%
+%\begin{macro}{basic string filter} \FE
+% This basic string filter will be used for \cs{FE@testopt} and \cs{FE@ifstar}. As far as\linebreak the later are used in
+% the definition of \cs{FE@modifiers} we can't use the \linebreak
+% \cmdref[DeclareStringFilter]{general string filter contructor} to do the job (infinite recursion).
+% \begin{macrocode}
+\long\def\ettl@BasicFilter#1#2#3/End§String/{\expandafter\ettl@B@sicFilter #1#3//#2/End§String//End§String/}
+\long\def\ettl@B@sicFilter#1/#2//#3/End§String/{@\ettl@nbk#3//%
+ {\ifcat $\detokenize{#1#2}$first\else second\fi}
+ {second}//oftwo}
+% \end{macrocode}
+%\end{macro}
+%
+% \begin{Macro}{FE@testopt}
+% Purely expandable |\@testopt|-like test:
+% \begin{macrocode}
+\newcommand\FE@testopt[3]{\ettl@FE@testopt#1/[/%
+ {#2#1}%
+ {#2[{#3}]{#1}}}%]
+\long\def\ettl@FE@testopt#1[#2/#3#{\csname @\ifcat $\detokenize{#1#2}$%
+ first\else second\fi oftwo\endcsname}
+% \end{macrocode}
+% \end{Macro}
+%
+% \iffalse
+%<package>
+%<package>%% \FE@ifstar{ #1 } { \StarredMacro }{ \NotStarredMacro }
+% \fi
+% \begin{Macro}{FE@ifstar}
+% Purely expandable |\@ifstar|-like test:
+% \begin{macrocode}
+\newcommand\FE@ifstar[3]{\ettl@FE@ifstar#1/*/%
+ {#2}%
+ {#3{#1}}}
+\long\def\ettl@FE@ifstar#1*#2/#3#{\csname @\ifcat $\detokenize{#1#2}$%
+ first\else second\fi oftwo\endcsname}
+% \end{macrocode}
+% \end{Macro}
+%
+% \iffalse
+%<package>
+%<package>%% \FE@charequal{ #1 } { \MacroWith= }{ \NormalMacro } % used by the string filters
+% \fi
+%
+%\begin{macro}{\FE@ifcharequal} \FE
+% This is the same as \cs{FE@ifstar} but for \CH{=} character (used in \cmdref*{DeclareStringFilter}):
+% \begin{macrocode}
+\newcommand\FE@ifcharequal[3]{\ettl@FE@charequal#1/=/%
+ {#2}%
+ {#3{#1}}}
+\long\def\ettl@FE@charequal#1=#2/#3#{\csname @\ifcat $\detokenize{#1#2}$%
+ first\else second\fi oftwo\endcsname}
+% \end{macrocode}
+%\end{macro}
+%
+% \iffalse
+%<package>
+%<package>%% \ettl@strfilt@dot{ #1 } { \MacroWith= }{ \NormalMacro } % used by the string filters
+% \fi
+%
+%\begin{macro}{\ettl@ifchardot} \FE
+% Used by |\ettl@strfilt@mod| to test if a character is a dot. It is used internally and is not the same
+% as |\FE@ifchar.|
+% \begin{macrocode}
+\newcommand\ettl@ifchardot[1]{\ettl@FE@chardot#1/./}
+\long\def\ettl@FE@chardot#1.#2/#3#{\csname @\ifcat $\detokenize{#1#2}$%
+ first\else second\fi oftwo\endcsname}
+% \end{macrocode}
+%\end{macro}%
+%
+% \iffalse
+%<package>
+%<package>%% \FE@ifchar{ <Character> }{ #1 }{ \SpecialFormMacro }{ \NormalMacro }
+% \fi
+% \begin{Macro}{FE@ifchar}
+% \cs{FE@ifchar} test if the character token following the macro is a single character equal to \prm{Character}:§
+% USAGE:¤|\FE@ifchar{|\prm{Character}|}{|\#1|}{\SpecialFormMacro}{\NormalMacro}|:
+% \begin{macrocode}
+\newcommand\FE@ifchar[4]{\ifsinglechar{#1}{#2}{#3}{#4{#2}}}
+% \end{macrocode}
+% \end{Macro}
+%
+% \iffalse
+%<package>
+%<package>%% \FE@modifiers{ Allowed Characters }{ #1 }{ \MacroA }{ \MacroB }{ \MacroC }...{ \MacroZ }{ \MacroDefault }
+% \fi
+%\begin{Macro}{FE@modifiers}
+% \cs{FE@modifiers} test if the character token following the macro is in the list of \prm{Allowed Characters}: USAGE:§
+% |\FE@modifiers{|\prm{Allowed Characters}|}{|\#1|}{\MacroA}|...|{\MacroZ}{\NormalMacro}|:
+% \begin{macrocode}
+\newcommand\FE@modifiers[2]{%
+ \ifOneToken{#2}%
+ {\ExpandAftercmds\ettl@FE@modifiers%
+ {\ExpandAftercmds{\ettl@setresult 12of3><}
+ {\ettl@getsinglelist{\ettl@ifchar{#2}}{#1}}}{#2}}
+ {\ExpandNextTwo{\ettl@supergobble[{{#2}}]}{-1}{\getcharlistcount{#1}+1}}}
+\long\def\ettl@FE@modifiers#1#2#3{\expandafter\ettl@supergobble%
+ \expandafter[\romannumeral-`\q\ifnum#2<0 \@swap{{#3}}\fi]{#2}{#1+1}}
+% \end{macrocode}
+%\end{Macro}
+%
+% \iffalse
+%<package>
+%<package>%% \ettl@supergobble{ p }{ q }{token_1}{token_2}...{token_p}{TOKEN_p+1}{token_p+2}...{token_p+q+1}
+% \fi
+%\begin{Macro}{ettl@supergobble}
+% \cs{ettl@supergobble} gobbles the $n$ first (groups of) tokens in the following list of $N$ (groups of) tokens
+% and expands the $n+1$. The macro is optimized (cf \cs{ettl@supergobbleeight} etc.) to avoid too long loops.
+% \begin{macrocode}
+\newcommand\ettl@supergobble[1]{\FE@testopt{#1}\ettl@superg@bble{}}
+\long\def\ettl@superg@bble[#1]#2#3{%
+% #1 = commands to put after the list (optional)
+% #2 = number to gobble first
+% #3 = total number of items
+ \ifnum\numexpr#3>0
+ \ifnum\numexpr#3-(#2)=0
+ \ettl@supergobble@loop{#3+2}0{\ettl@supergobble@end{}{}}%
+ \else
+ \expandafter\ettl@supergobble@loop\expandafter{%
+ \number\numexpr\ifnum\numexpr#2*(#2-(#3))>0 #3+1\else#2+2\fi}{#3+2}%
+ {\ettl@supergobble@next{}{#1}}%
+ \fi\fi}
+\long\def\ettl@supergobble@loop#1#2#3{%
+ \ifcsname ettl@supergobble\number\numexpr#1\endcsname
+ \csname ettl@supergobble\number\numexpr#1\endcsname
+ {#3{#2-(#1)-1}}%
+ \else\ettl@supergobbleeight{\ettl@supergobble@loop{#1-8}{#2-8}{#3}}%
+ \fi}
+\long\def\ettl@supergobble@end#1#2#3{\fi\fi\fi#1#2}
+\long\csdef{ettl@supergobbleeight}#1\fi#2#3#4#5#6#7#8#9{\fi#1}
+\long\csdef{ettl@supergobble7}#1#2\fi#3#4#5#6#7#8#9{#1}
+\long\csdef{ettl@supergobble6}#1#2\fi#3#4#5#6#7#8{#1}
+\long\csdef{ettl@supergobble5}#1#2\fi#3#4#5#6#7{#1}
+\long\csdef{ettl@supergobble4}#1#2\fi#3#4#5#6{#1}
+\long\csdef{ettl@supergobble3}#1#2\fi#3#4#5{#1}
+\long\csdef{ettl@supergobble2}#1#2\fi#3#4{#1}
+\long\csdef{ettl@supergobble1}#1#2\fi#3{#1}
+\long\csdef{ettl@supergobble0}#1#2\fi{#1}
+\long\def\ettl@supergobble@next#1#2#3#4{\fi
+ \ettl@supergobble@loop{#3}0{\ettl@supergobble@end{#4}{#2}}}
+% \end{macrocode}
+%\end{Macro}
+%
+%
+% \Subsection{Define control sequence through groups}
+%
+%\iffalse
+%<package>
+%<package>%% \AfterGroup{ code } / \AfterGroup*{ code } the star form expands its argument once
+%\fi
+%
+%\begin{Macro}{AfterGroup}
+%\begin{Macro*}{AfterGroup*}
+% \cs{AfterGroup} enhances the \cs{aftergroup} primitive: arbitrary code may be given to \cs{AfterGroup}.
+% We use the |\edef|...|\unexpanded| trick already implemented in \cmdref*{ettl@ifnextchar} to allow macro
+% definitions (with arguments) inside the argument of \cs{AfterGroup}:
+% \begin{macrocode}
+\newcount\ettl@fter
+\newrobustcmd\AfterGroup{\@ifstar{\ettl@AfterGroup\@firstofone}{\ettl@AfterGroup\unexpanded}}
+\newrobustcmd\ettl@AfterGroup[2]{%
+ \csxdef{ettl@fterGroup\number\numexpr\the\ettl@fter+1}%
+ {\global\csundef{ettl@fterGroup\number\numexpr\the\ettl@fter+1}#1{#2}}%
+ \global\advance\ettl@fter\@ne
+ \expandafter\aftergroup\csname ettl@fterGroup\the\ettl@fter\endcsname}
+% \end{macrocode}
+%\end{Macro*}
+%\end{Macro}
+%
+%\iffalse
+%<package>
+%<package>%% \AfterAssignment{ code }
+%\fi
+%
+%\begin{Macro}{AfterAssignment}
+% \cs{AfterAssignment} can be given arbitray code:
+% \begin{macrocode}
+\newrobustcmd\AfterAssignment{\@ifstar{\ettl@AfterAssignment\@firstofone}{\ettl@AfterAssignment\unexpanded}}
+\newrobustcmd\ettl@AfterAssignment[2]{%
+ \csedef{ettl@afterassignment@hook\number\numexpr\the\ettl@fter}{#1{#2}}%
+ \global\advance\ettl@fter\@ne
+ \expandafter\afterassignment\csname ettl@afterassignment@hook\the\ettl@fter\endcsname}
+% \end{macrocode}
+%\end{Macro}
+%
+%\iffalse
+%<package>
+%<package>%% \aftergroup@def{ cs-token }
+%\fi
+%
+%
+% \begin{Macro}{aftergroup@def}
+% The macro is based on \xpackage{letltxmacro} package. Therefore, \cs{aftergroup@def} works with commands with optional
+% arguments and with the ones defined using \LaTeX's \cs{DeclareRobustCommand}.
+% {\rmk: we could have used the \cmdref*{AfterGroup} macro but execution is lighter with $5$ calls to \cs{aftergroup} primitive.}:§§
+% \begin{macrocode}
+\newrobustcmd*\aftergroup@def{\@ifstar\aftergroup@defstar\aftergroup@d@f}
+\newrobustcmd*\@ftergroup@def[3]{%
+ \aftergroup#2\aftergroup#3\aftergroup#1%
+ \aftergroup\global \aftergroup\undef \aftergroup#1}
+\newrobustcmd*\aftergroup@defstar[1]{%
+ \global\expandafter\let\csname ettl@ftergroup@def\the\numexpr\ettl@fter+1\endcsname#1%
+ \global\advance\ettl@fter\@ne
+ \expandafter\@ftergroup@def\csname ettl@ftergroup@def\the\ettl@fter\endcsname\let#1}
+\newrobustcmd*\aftergroup@d@f[1]{%
+ \let\etex@let@primitive\let \def\let{\global\etex@let@primitive}%
+ \expandafter\LetLtxMacro\csname ettl@ftergroup@def\the\numexpr\ettl@fter+1\endcsname#1%
+ \global\advance\ettl@fter\@ne
+ \etex@let@primitive\let=\etex@let@primitive
+ \expandafter\@ftergroup@def\csname ettl@ftergroup@def\the\ettl@fter\endcsname\LetLtxMacro#1}%
+\let\ettl@aftergroup@def\aftergroup@def
+% \end{macrocode}
+% \end{Macro}
+%
+% \Subsection{\textbackslash futuredef}
+%
+% \iffalse
+%<package>%----------------------------------------------------------------------------
+%<package>
+%<package>%% \@ifchar{ single token }{ true }{ false }
+%<package>
+% \fi
+%
+%\begin{Macro}{@ifchar}
+% \cs{@ifchar} works just like \cs{@ifstar} but uses the \cmdref={character-test}.
+% \begin{macrocode}
+\long\def\@ifchar#1#2{\ettl@ifnextchar #1{\@firstoftwo{#2}}}
+% \end{macrocode}
+%\end{Macro}
+%
+% \iffalse
+%<package>
+%<package>%% \@char@testopt{ code }{ single token }{ default value }{ single token }
+%<package>
+% \fi
+%
+% \begin{Macro}{@char@testopt}
+% \cs{@char@testopt} is a generalisation of \cs{@testopt} for other pairs of character than \string[ and \string]
+% to pass optional parameters to macros. It is based on \cmdref{ettl@ifnextchar} and therefore on the \cmdref={character-test}.
+% \begin{macrocode}
+\newcommand\@char@testopt[4]{\ettl@ifnextchar#2{#1}{#1#2#3#4}}
+% \end{macrocode}
+% \end{Macro}
+%
+% \iffalse
+%<package>
+%<package>%% \@ifnextchardigit{ true }{ false }
+%<package>
+% \fi
+% \iffalse
+% \begin{Macro}{@ifnextchardigit}
+% \begin{macrocode}
+\newrobustcmd\@ifnextchardigit[2]{\begingroup
+
+ \endgroup
+}% \@ifnextchardigit
+% \end{macrocode}
+% \end{Macro}
+% \fi
+%
+% \iffalse
+%<package>
+%<package>%% \ettl@ifnextchar{ character token }{ true }{ false }
+%<package>
+% \fi
+%
+%\begin{Macro}{ettl@ifnextchar}
+% \cs{ettl@ifnextchar} is based on the \cmdref={character-test} rather than the |\ifx|-test. See the example for
+% explanation on its behaviour.§
+% \csbf{ettl@ifnextchar} is used in the definition of \cmdref*{aftergroup@def} and \cmdref*{@ifchar} (of course...).§
+% We take advantage of delimited definitions to exit from |\if|...|\fi| conditionnals (even in the case where
+% the macro parameter is |\else|, |\if| or |\fi|...):
+% \begin{macrocode}
+\newrobustcmd\ettl@ifnextchar[3]{\begingroup
+ \long\edef\1##1/##2/##3{##1\endgroup\unexpanded{#2}##3}%
+ \long\edef\2##1/##2/##3{##1\endgroup\unexpanded{#3}##3}%
+ \ifOneToken{#1}
+ {\csname ettl@\ifcat $\expandafter\ettl@cdr\detokenize{#1}\@nil$% OneChar
+ xifnch\else xifntk\fi\endcsname{#1}}
+ {\2//{}}}
+% \end{macrocode}
+% \end{Macro}
+%
+% \begin{macro}{\ettl@xifnch}
+%\begin{macro}{\ettl@ifnch}
+% \cs{ettl@xifnch} is used in case the token to test (first parameter of \cs{ettl@ifnextchar} is a character token.
+% It gobbles the possible spaces and exits at one if a begin-group or end-group character is found:
+% \begin{macrocode}
+\long\def\ettl@xifnch#1{%
+ \ifx#1\@sptoken \def\ettl@xifnch{\ifx\@let@token\@sptoken\1\else\2\fi//{}}%
+ \else \def\ettl@xifnch{%
+ \ifx\@let@token\bgroup \2
+ \else\ifx\@let@token\egroup \2
+ \else\ifx\@let@token\@sptoken \ettl@ifnspace\ettl@xifnch
+ \else\ettl@ifnch
+ \fi\fi\fi/{#1}/{}}%
+ \fi\futurelet\@let@token\ettl@xifnch}
+% \end{macrocode}
+% \cs{ettl@ifnch} does the final comparison: the token is taken into the macro parameter
+% to check if it is a single character (it was not possible to ensure this point for active characters that
+% have been |\let| to something, unless by eating it in the parameter of a macro. It the test fails,
+% the parameters is appended again to the input):
+% \begin{macrocode}
+\long\def\ettl@ifnch#1/#2/#3{#1\long\def\ettl@ifnch##1{\ettl@char{##1}
+ {\if\string##1\string#2\1\else\2\fi}\2//{##1}}\ettl@ifnch}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\ettl@xifntk}
+%\begin{macro}{\ettl@ifntk}
+% \cs{ettl@xifntk} is quite the same as \cs{ettl@xifnch} but for the case the token to test (\ie the first parameter
+% of \cs{ettl@ifnextchar} is a control sequence:
+% \begin{macrocode}
+\long\def\ettl@xifntk#1{%
+ \ifx#1\bgroup\def\ettl@xifntk{\ifx\@let@token\bgroup\1\else\2\fi//{}}%
+ \else\ifx#1\egroup\def\ettl@xifntk{\ifx\@let@token\egroup\1\else\2\fi//{}}%
+ \else\def\ettl@xifntk{%
+ \ifx\@let@token\bgroup \2
+ \else\ifx\@let@token\egroup \2
+ \else\ifx\@let@token\@sptoken \ettl@ifnspace\ettl@xifntk%
+ \else\ettl@ifntk%
+ \fi\fi\fi/{#1}/{}}%
+ \fi\futurelet\@let@token\ettl@xifntk}
+% \end{macrocode}
+% \cs{ettl@ifntk} finishes the job. We need to ensure that |\@let@token| is not an active character having been
+% let to the token to test: there is no such thing as an active character for \cs{ettl@ifnextchar}!
+% \begin{macrocode}
+\long\def\ettl@ifntk#1/#2/#3{#1\long\def\ettl@ifntk##1{\ettl@char{##1}
+ \2{\ifx##1#2\1\else\2\fi}//{##1}}\ettl@ifntk}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\ettl@ifnspace}
+% \cs{ettl@ifnspace} is used to gobble a space and go back to the loop (this is very rare...):
+% \begin{macrocode}
+\long\def\ettl@ifnspace#1#2/#3/#4 {#2\futurelet\@let@token#1}
+% \end{macrocode}
+%\end{macro}
+%
+% \iffalse
+%<package>
+%<package>%% \futuredef[list of allowed tokens]{ command }{ commands to expand after }
+%<package>%% \futuredef*[list of allowed tokens]{ command }{ commands to expand after }
+%<package>%% \futuredef=[list of allowed tokens]{ command }{ commands to expand after }
+%<package>%% \futuredef*=[list of allowed tokens]{ command }{ commands to expand after } (or \futuredef=*[...] )
+% \fi
+%
+% \begin{Macro}{futuredef}
+% \begin{Macro*}{futuredef*}
+% \begin{Macro*}{futuredef=}
+% \begin{Macro*}{futuredef*=}
+% This is the scanner.
+% \begin{macrocode}
+\newrobustcmd*\futuredef{\begingroup\ettl@futdef\ettl@futuredef\detokenize}
+\protected\def\ettl@futdef#1#2{\@ifstar%
+ {\ettl@futdef\ettl@futured@f#2}
+ {\@ifchar={\ettl@futdef#1\unexpanded}
+ {\@testopt{\ettl@futur@def#1#2}{}}}}
+\long\def\ettl@futur@def#1#2[#3]{%
+ \csname ettl@\ifcat $\detokenize{#3}$1\else2\fi of2\endcsname
+ {\let \ettl@x \@empty \letcs \ettl@futur@def@collect{\@gobblescape#1@collectall}}%
+ {\def \ettl@x {#3}\edef \ettl@y {#2{#3}}%
+ \ifx\ettl@x\ettl@y \let\ettl@y\@gobble
+ \else \ifx#2\unexpanded \let\ettl@y\@gobble
+ \else \def\ettl@y{\edef\ettl@x}%
+ \fi\fi\ettl@y{\detokenizeChars{#3}}%
+ \letcs\ettl@futur@def@collect{\@gobblescape#1@collect}}%
+ \expandafter#1\expandafter#2\expandafter{\ettl@x}}
+% \end{macrocode}
+% \end{Macro*}
+% \end{Macro*}
+% \end{Macro*}
+% \end{Macro}
+%
+% \begin{macro}{futuredef (not starred)}
+% \cs{ettl@futuredef} defines the \textsfsl{test-macro} (which is entitled to break the loop) and the \textsfsl{loop-macro}:
+% \begin{macrocode}
+\long\def\ettl@futuredef#1#2#3#4{% #1=detokenize #2=list, #3=macro result, #4=code-next
+ \def \ettl@futuredef@loop{\ettl@futuredef@test{}}%
+ \long \def \ettl@futuredef@test##1{%
+ \ifcat\noexpand\ettl@x\bgroup\ettl@futuredef@end{}\else
+ \ifcat\noexpand\ettl@x\egroup\ettl@futuredef@end{}\else
+ \ifcat\noexpand\ettl@x\ettl@sptoken\ettl@futuredef@space#1\else
+ \ettl@futur@def@collect#1\fi\fi\fi/Ne¤t/{#2}{##1}}%
+ \long \def \ettl@futuredef@end##1##2/Ne¤t/##3##4{##2\endgroup\def#3{##4}#4##1}%
+ \futurelet \ettl@x \ettl@futuredef@loop}
+% \end{macrocode}
+% \cs{ettl@futuredef@collect} captures the next token (because it was found in the list) and selectively
+% append it to the \textsfsl{result} (the argument of \cs{ettl@futuredef@test}). Then it loops:
+% \begin{macrocode}
+\long\def\ettl@futuredef@collect#1#2/Ne¤t/#3#4#5{#2%
+ \ifcat\noexpand#5\relax \ettl@futuredef@filt\unexpanded
+ \else \ettl@futuredef@filt#1
+ \fi{#5}{#3}
+ {\def\ettl@futuredef@loop{\ettl@futuredef@test{#4#5}}\futurelet\ettl@x\ettl@futuredef@loop}
+ {\ettl@futuredef@end{#5}/Ne¤t/{}{#4}}/Ne¤t/}
+% \end{macrocode}
+% \cs{ettl@futuredef@space} gobbles the space token and append a space to the \textsfsl{result}. Then it loops:
+% \begin{macrocode}
+\long\def\ettl@futuredef@space#1#2/Ne¤t/#3#4 {%
+ \ettl@futur@def@collect#1#2/Ne¤t/{#3}{#4}{ }}
+% \end{macrocode}
+% \cs{ettl@futuredef@collectall} is used when no option (no \prm{list of allowed tokens}) has been given to \cs{futuredef}.
+% In this case, \cs{futuredef} will stop only at the next begin-group or end-group token:
+% \begin{macrocode}
+\long\def\ettl@futuredef@collectall#1#2/Ne¤t/#3#4#5{#2%
+ \def\ettl@futuredef@loop{\ettl@futuredef@test{#4#5}}\futurelet\ettl@x\ettl@futuredef@loop}
+% \end{macrocode}
+% \end{macro}
+%
+%\begin{macro}{\ettl@futur@def@filt}
+% \cs{ettl@futur@def@filt} defines the \textslsf{filter macro} to check if the token is in the \prm{list of allowed tokens}:
+% \begin{macrocode}
+\long\def\ettl@futur@def@filt#1#2{% #1=token to check, #2=allowed list
+ \long\def\ettl@futdef@filt##1#1##2##3/##4##5##6/Ne¤t/{##5}%
+ \ettl@futdef@filt#2#1//}
+\long\def\ettl@futuredef@filt#1#2\fi#3#4{\fi % #1=detokenize/unexpanded, #2=discard, #3=token,#4=allowed list
+ \expandafter\ettl@futur@def@filt\expandafter{#1{#3}}{#4}}
+% \end{macrocode}
+%\end{macro}
+%
+% \begin{macro}{futured@f (starred)} \cmdlabel{impl:starredfuturedef}
+% \cs{ettl@futured@f} defines the \textsfsl{test-macro} (which is entitled to break the loop) and the \textsfsl{loop-macro}:
+% \begin{macrocode}
+\long\def\ettl@futured@f#1#2#3#4{% #1=detokenize #2=list, #3=macro result, #4=code-next
+ \let \ettl@y \@undefined
+ \def \ettl@futured@f@loop{\ettl@futured@f@test{}}%
+ \long \def \ettl@futured@f@test##1{%
+ \ifcat\noexpand\ettl@x\bgroup\ettl@futured@f@end\else
+ \ifcat\noexpand\ettl@x\egroup\ettl@futured@f@end\else
+ \ifcat\noexpand\ettl@x\ettl@sptoken\ettl@futured@f@space#1\else
+ \ettl@futur@def@collect#1\fi\fi\fi/Ne¤t/{##1}{#2}{}}%
+ \long \def \ettl@futured@f@end##1/Ne¤t/##2##3##4{##1\endgroup\def#3{##2}#4##4}%
+ \futurelet \ettl@x \ettl@futured@f@loop}
+\long\def\ettl@futured@f@space#1#2/Ne¤t/#3#4#5 {%
+ \ettl@futur@def@collect#1#2/Ne¤t/{#3}{#4}{#5}{ }}
+% \end{macrocode}
+% \cs{ettl@futured@f@collect} collects the next token which is appended to the argument of \cs{ettl@futured@f@test} (the \textsfsl{result})
+% if it is in the \prm{list of allowed tokens}, otherwise expansion is tried:
+% \begin{macrocode}
+\long\def\ettl@futured@f@collect#1#2/Ne¤t/#3#4#5#6{#2%
+ \ifcat\noexpand\ettl@x\relax \ettl@futuredef@filt\unexpanded
+ \else \ettl@futuredef@filt#1
+ \fi{#6}{#4}
+ {\let \ettl@y \@undefined \ettl@futured@f@append/Ne¤t/{#3}{}{#6}}%
+ {\ettl@futured@f@try@expand{#3}\ettl@futured@f@end{#6}}/Ne¤t/}
+% \end{macrocode}
+% \cs{ettl@futured@f@collectall} is used when \cs{futuredef*} is called with an empty optional argument:
+% \begin{macrocode}
+\long\def\ettl@futured@f@collectall#1#2/Ne¤t/#3#4#5#6{#2%
+ \ettl@futured@f@try@expand{#3}\ettl@futured@f@append{#6}}
+% \end{macrocode}
+% \cs{ettl@futured@f@space} is used in case the token is a space token:
+% \begin{macrocode}
+\long\def\ettl@futured@f@space#1#2/Ne¤t/#3#4#5 {%
+ \ettl@futur@def@collect#1#2/Ne¤t/{#3}{#4}{#5}{ }}
+% \end{macrocode}
+% \cs{ettl@futured@f@try@expand} checks if the token shall be expanded, or if the loop shall be broken (in case the
+% \prm{list of allowed tokens} is specified) or if this token shall be appended to the result
+% (in case the \prm{list of allowed token} is empty):
+% \begin{macrocode}
+\long\def\ettl@futured@f@try@expand#1#2#3{%
+ \expandafter\ifx\noexpand\ettl@x\ettl@x
+ \let\ettl@y=#2%
+ \else\ettl@futured@f@CheckSpecials{#3}%
+ {\let \ettl@y=#2}%
+ {\ifx\ettl@x\ettl@y \let \ettl@y \ettl@futured@f@end\else
+ \let \ettl@y \ettl@futured@f@expand\fi}%
+ \fi\ettl@y/Ne¤t/{#1}{}{#3}}
+% \end{macrocode}
+% \cs{ettl@futured@f@expand} expands the next token because it is not in the list and
+% goes back to the loop:
+% \begin{macrocode}
+\long\def\ettl@futured@f@expand/Ne¤t/#1#2#3{\let\ettl@y\ettl@x
+ \expandafter\futurelet\expandafter\ettl@x\expandafter\ettl@futured@f@loop#3}
+% \end{macrocode}
+% \cs{ettl@futured@f@CheckSpecials} checks if the token is undefined or a |\if|... or |\else| etc. This is compulsory
+% because we do not have to attempt expansion of such tokens (unless we want to get an error from \TeX):
+% \begin{macrocode}
+\long\def\ettl@futured@f@CheckSpecials#1{\ifintokslist{#1}{%
+ \@undefined\if\ifcat\ifnum\ifdim\ifodd%
+ \ifvmode\ifhmode\ifmmode\ifinner\ifvoid\ifhbox\ifvbox%
+ \ifx\ifeof\iftrue\iffalse\ifcase\ifdefined\ifcsname\iffontchar%
+ \else\fi\or}}
+% \end{macrocode}
+% Finally, \cs{ettl@futured@f@append} appends the token to the result and goes back to the loop:
+% \begin{macrocode}
+\def\ettl@futured@f@append/Ne¤t/#1#2#3{%
+ \def\ettl@futured@f@loop{\ettl@futured@f@test{#1#3}}%
+ \futurelet\ettl@x\ettl@futured@f@loop}%
+% \end{macrocode}
+% \end{macro}
+%
+% \iffalse
+%<package>
+%<package>%----------------------------------------------------------------------------
+% \fi
+%
+% \Subsection{Loops and Lists Management}
+%
+% \subsubsection{naturalloop}
+%
+% \iffalse
+%<package>
+%<package>%% \naturalloop [ auxiliary commands (default \do) ]{ n times }{ argument }
+% \fi
+%
+% \begin{Macro}{naturalloop}
+% This macro uses the capability of \eTeX{} to build purely expandable loop using \cs{numexpr}:
+% \begin{macrocode}
+\newcommand\naturalloop[1]{\FE@testopt{#1}\ettl@naturalloop{\do}}
+\def\ettl@naturalloop[#1]#2#3{%
+ \ifnum\numexpr#2>0 \expandafter\@swaparg\expandafter{\romannumeral-`\q#1[0]{#3}{#3}}%
+ {\ettl@naturall@@p[{#1}]{#2-1}{0}{#3}}
+% \ExpandNext{\ettl@naturall@@p[{#1}]{#2-1}{1}{#3}}{#1[1]{#3}{#3}}%
+ \else\@swap{\unexpanded{#3}}%
+ \fi}
+\def\ettl@naturall@@p[#1]#2#3#4#5#6\fi{\fi%
+ \ifnum\numexpr#2>0 \expandafter\@swaparg\expandafter{\romannumeral-`\q%
+ \expandafter\@swap\expandafter{\expandafter[\number\numexpr#3+1]}{#1}{#4}{#5}}%
+ {\ettl@naturall@@p[{#1}]{#2-1}{#3+1}{#4}}%
+ \else\@swap{\unexpanded{#5}}%
+ \fi}
+% \end{macrocode}
+%
+% \end{Macro}
+%
+% \subsubsection{Lists of single tokens}
+%
+% \iffalse
+%<package>
+%<package>%% \ifinttokslist{ item }{ list of tokens }{ true }{ false }
+% \fi
+%
+%\begin{Macro*}{ifintokslist} \FE
+% \cs{ifintokslist}\prm{token}\prm{list of single tokens} breaks the loop at once when \prm{token}
+% is found in the list. The test for the end of the list is made by \cs{ettl@nbk}... of course:
+%\begin{Macro}{ifincharlist}
+% \cs{ifincharlist}\prm{character or token}\prm{list of single characters or tokens} is the same, with a
+% different test macro: \cs{ettl@ifchar} is used instead of \cs{ettl@ifx}:
+% \begin{macrocode}
+\newcommand\ifintokslist[2]{\romannumeral\csname rmn@%
+ \expandafter\ettl@nbk\romannumeral\ettl@dosinglelist{\ettl@ifintokslist{#1}}{#2}\z@//%
+ {first}{second}//oftwo\endcsname}
+\long\def\ettl@ifintokslist#1#2{\ifx#1#2\ettl@breakloop\z@\fi}
+\newcommand\ifincharlist[2]{\romannumeral\csname rmn@%
+ \expandafter\ettl@nbk\romannumeral\ettl@dosinglelist{\ettl@ifincharlist{#1}}{#2}\z@//%
+ {first}{second}//oftwo\endcsname}
+\long\def\ettl@ifincharlist#1#2{\ettl@ifchar{#1}{#2}{\ettl@breakloop\z@}{}}
+% \end{macrocode}
+%\end{Macro}
+%\end{Macro*}
+%
+%\begin{macro}{\ettl@dosinglelist} \FE
+% We define a very simple loop for single tokens (for internal use): it is the same as \cs{toksloop} but
+% avoids overhead due to the parsing of modifiers:
+% \begin{macrocode}
+\long\def\ettl@dosinglelist#1#2{\ettl@nbk#2//%
+ {\ettl@dosinglelist@loop{#1}#2//{\ettl@dosinglelist@loop{#1}}{\ettl@breakloop{}}}
+ {\ettl@breakloop{}}///End§List/}
+\long\def\ettl@dosinglelist@loop#1#2#3#4/#5#6#7/End§List/{%
+ #1{#2}#6{#3}#4//{#6}{#7}/End§List/}
+% \end{macrocode}
+%\end{macro}
+%
+% \iffalse
+%<package>
+%<package>%% \gettokslistindex { item }{ list of tokens }
+%<package>%% \gettokslistcount { item }{ list of tokens }
+%<package>%% \gettokslisttoken { item }{ list of tokens }
+% \fi
+%
+% \begin{Macro*}{gettokslistindex}
+% \begin{Macro*}{getcharlistindex}
+% \begin{Macro*}{gettokslistcount}
+% \begin{Macro*}{getcharlistcount}
+% \begin{Macro*}{gettokslisttoken}
+% \begin{Macro}{getcharlisttoken}
+%
+% \cs{gettokslistindex}\prm{item}\prm{tokenlist-macro}
+%
+% \cs{gettokslistindex} is always purely expandable (|\ifx| test).
+%
+% The following three macros are the \textsl{entry points}.
+% \cs{ExpandAftercmds} is applied to \cs{ettl@getsinglelist} which initiates the loop: we ask for total expansion.
+% After expansion, \cs{ettl@setresult} will extract the wanted register by projection:
+% The result comes from in the first
+% register for \textvb{count}, the second for \textvb{index} and the third for \textvb{token}, therefore, we use the
+% \cs{ettl@XofY} macros:
+% \begin{macrocode}
+\newcommand\gettokslistindex[2]{\number\ifnotempty{#2}{\ettl@nbk#1//%
+ {\ExpandAftercmds{\ettl@setresult 2of3><}{\ettl@getsinglelist{\ettl@ifx{#1}}{#2}}}
+ {-1}//}{-1}}
+\newcommand\getcharlistindex[2]{\number\ifnotempty{#2}{\ettl@nbk#1//%
+ {\ExpandAftercmds{\ettl@setresult 2of3><}{\ettl@getsinglelist{\ettl@ifchar{#1}}{#2}}}
+ {-1}//}{-1}}
+\newcommand\gettokslistcount[1]{\number\ifnotempty{#1}%
+ {\ExpandAftercmds{\ettl@setresult 1of3><}{\ettl@getsinglelist{\ettl@ifx{\\}}{#1}}}
+ 0}
+\newcommand\getcharlistcount[1]{}%
+\let\getcharlistcount=\gettokslistcount
+\newcommand\gettokslisttoken[2]{\ifnotempty{#2}{\ettl@nbk#1//%
+ {\ExpandAftercmds{\ettl@setresult 3of3><}{\ettl@getsinglelist{\ettl@ifx{#1}}{#2}}}
+ {}//}{}}
+\newcommand\getcharlisttoken[2]{\ifnotempty{#2}{\ettl@nbk#1//%
+ {\ExpandAftercmds{\ettl@setresult 3of3><}{\ettl@getsinglelist{\ettl@ifchar{#1}}{#2}}}
+ {}//}{}}
+% \end{macrocode}
+% \cs{ettl@getsinglelist}\cmdlabel{impl:ettl@getsinglelist} initiates the loop (we test if the list or the \prm{item} is empty first):
+% \begin{macrocode}
+\long\def\ettl@getsinglelist#1#2{\ettl@singlelist@loop{-1}{-1}{}#2//%
+ {\ettl@expandafthree\ettl@singlelist@loop#1}%
+ {\expandafter\ettl@singlelist@result\@thirdofthree}/End§List/}
+% \end{macrocode}
+% \cs{ettl@singlelist@loop} tests each token and update registers:
+% \begin{macrocode}
+\long\def\ettl@singlelist@loop#1#2#3#4#5/#6#7#8/End§List/{%
+ #7{#4}
+ {{#1+1}{#2+1+0*(0}{#4}}
+ {{#1+1}{#2+1}{#3}}#5//{#7}{#8}/End§List/}
+ % \csname @#1#5{first}{second}oftwo\endcsname
+ % {#8{#1}{#2+1}{#3+1+0*(0}{#5}#6//#8#9}
+ % {#8{#1}{#2+1}{#3+1}{#4}#6//#8#9}/End§List/}
+% \end{macrocode}
+
+% Well! \#1 is the \textsl{test-macro} to test against \#5, the current token of the list.
+%
+% \#2 is the current index. It is incremented by $1$ and will be equal to the length of the list, at the end.
+% \#3 is the index of the \prm{item} (if found): it is incremented by $1$ but at the time
+% \prm{item} is found is the list, the next increments are canceled (multiplication by $0$).
+%
+% The fourth parameter remains the same (\#4=\#4=|empty|, set at the initiation of the loop) but at the time \prm{item}
+% is found, \#4 becomes this \prm{item} (precisely the matching item found in the list: \#5).
+%
+% \#6 is the remainder of the list. \#7, \#8 and \#9 are the usual parameter for \textsfsl{blank-test} (see \cmdref*{ettl@nbk}).
+%
+% \cs{ettl@tokslist@result} extracts the |count|, the |index| and the |token| from the parameters of the \textsl{test-macro}:
+% \begin{macrocode}
+\def\ettl@singlelist@result#1#2#3#4/End§List/{\ExpandNextTwo\@swaptwo%
+ {\number\numexpr\ifempty{#3}{-1}{#2)}}{\number\numexpr#1}{#3}}
+% \end{macrocode}
+% Then \cs{ettl@setresult} finishes the job:
+% \begin{macrocode}
+\def\ettl@setresult#1of#2>#3<{\ettl@nbk #3//%
+ {\ettl@set@result#1of#2>#3<}
+ {\csname ettl@#1of#2\endcsname}//}
+\def\ettl@set@result#1of#2>#3<#4{\ifdefcount{#3}
+ {#3=\csname ettl@#1of#2\endcsname#4}
+ {\expandafter\edef\noexpand#3{\csname ettl@#1of#2\endcsname{#4}}}%
+}
+% \end{macrocode}
+% \end{Macro}
+% \end{Macro*}
+% \end{Macro*}
+% \end{Macro*}
+% \end{Macro*}
+% \end{Macro*}
+%
+% \subsubsection{General Lists and Loops Constructor}
+%
+% \begin{Macro}{DeclareCmdListParser}
+%
+% |\DeclareCmdListParser| acts in the same way as
+% \xpackage{etoolbox}-|\DeclareListParser| and the command-list-parser
+% are sensitive to the category code of the \prm{separator}
+%
+% \iffalse
+%<package>
+%<package>%% \DeclareCmdListParser : general constructor for command-list parsers
+%<package>%% \DeclareCmdListParser\ParserName{separator}
+% \fi
+%
+% The command-list-parser will be defined only if it is definable:
+% \begin{macrocode}
+\newrobustcmd\DeclareCmdListParser[3][\global]{\@ifdefinable{#2}{\begingroup
+ \protected\def\ettl@defcmdparser##1{%
+ \edef\ettl@defcmdparser{\endgroup\ettl@defcmdparser
+ {#1}{\noexpand#2}{\unexpanded{#3}}
+ {\noexpandcs{##1->start}}
+ {\noexpandcs{##1->loop}}
+ {\noexpandcs{##1->loop+}}
+ {\noexpandcs{for##1}}%
+ }\ettl@defcmdparser
+ }\expandafter\ettl@defcmdparser\expandafter{\romannumeral-`\q\@gobblescape#2}}}
+% \end{macrocode}
+% \cs{ettl@defcmdparser} does the definitions: \cs{parser->start} initiates the loop (and add a separator
+% at the end of the list) and \cs{parser->loop} loops into the list, expanding the (optional, default |\do|) user code
+% for each item.
+%
+% In case the \CH{\ttbf+} form is used, the auxiliary macro \cs{ettl@doitemidx} overloads
+% the user-code. Otherwise (simple form without index): \cs{ettl@doitem} overloads the user-code.
+% \begin{macrocode}
+\protected\long\def\ettl@defcmdparser#1#2#3#4#5#6#7{%#1=global,#2=command,#3=sep,#4=start,#5=loop,#6=loop+
+ #1\long\def#4##1##2[##3]##4{% ##1=case, ##2=expandafter??? , ##3=do, ##4=list
+ ##2{##4}% ifiscs or @thirdofthree
+ {\expandafter\@swaparg\expandafter{##4}{#4{##1}\@thirdofthree[{##3}]}}
+ {\ettl@nbk##4//%
+ {\ifcase##1 \ettl@or\@swaplast{\number\numexpr#60{\ettl@lst@count}}#6%
+ \or \ettl@or\@swaplast{#60{\ettl@lst@getitem{##3}}}#6%
+ \or \ettl@or\@swaplast{#5{##3}}#5%
+ \or \ettl@fi\@swaplast{#60{##3}}#6%
+ \fi{##4#3//}{\ettl@breakloop{\ifx##10\expandafter\relax\fi}}%
+ }{\ettl@breakloop{}}///End§List/}}%
+ #1\long\def#5##1##2#3##3##4/##5##6##7/End§List/{%
+ \ifcat $\detokenize{##2}$\expandafter\@gobbletwo\fi\@firstofone{##1{##2}}%
+ ##6{##1}##3##4//{##6}{##7}/End§List/}
+ #1\long\def#6##1##2##3#3##4##5/##6##7##8/End§List/{%
+ \ifcat $\detokenize{##3}$\expandafter\@gobbletwo\fi\@firstofone{##2[##1]{##3}}%
+ \expandafter##7\expandafter{\number\numexpr##1+1}{##2}##4##5//{##7}{##8}/End§List/}
+ #1\protected\def#7{\@ifchar*%
+ {\@ifchar+{\ettl@forloop{\expandafter#2\expandafter*\expandafter+}{[####1]####2}}
+ {\ettl@forloop{\expandafter#2\expandafter*}{####1}}}
+ {\@ifchar+{\@ifchar*%
+ {\ettl@forloop{\expandafter#2\expandafter*\expandafter+}{[####1]####2}}
+ {\ettl@forloop{\expandafter#2\expandafter+}{[####1]####2}}}
+ {\ettl@forloop{\expandafter#2}{####1}}}}
+ #1\def#2{\ettl@lst@modif#423\ifiscs}}
+% \end{macrocode}
+% \cs{ettl@lst@doitem} gives the current item to the auxiliary macro, while \cs{ettl@lst@doitemidx} gives the index as well.
+% \cs{ettl@lts@getitem} is the helper macro in case we ask for an item (cf. |\csvloop[4]\mylist|) and
+% \cs{etttl@lst@count} is as basic as it can be!
+% \begin{macrocode}
+\long\def\ettl@lst@getitem#1[#2]#3{%
+ \ifnum\numexpr#1<0 \@swap{\breakloop{}}\fi
+ \ifnum\numexpr#1=#2 \@swap{\breakloop{#3}}\fi}
+\long\def\ettl@lst@count[#1]#2{+\ettl@nbk#2//10//}
+% \end{macrocode}
+%\end{Macro}
+%
+% \begin{macro}{\ettl@lst@modif} \cmdlabel{impl:ettl@lst@modif} \FE
+% \cs{ettl@lst@modif} is used by any command-list-parser at the beginning to set the options. This macro is interesting
+% because it is recursive: each allowed modifier is parsed one after the other in a purely expandable way, setting
+% the registers (\#1 to \#4) to the value corresponding to the modifier used (the registers are initialized to their default value).
+%
+% Such a code is interesting because it may be used elsewhere: the aim is to parse modifiers without taking care of their
+% order (\cs{csvloop}\stform*\stform+ is the same as \cs{csvloop}\stform{+*}):
+% \begin{macrocode}
+\long\def\ettl@lst@modif#1#2#3#4#5{\FE@modifiers{*+![}{#5}%
+ {\ettl@lst@modif{#1}#2#3\@thirdofthree}% * case
+ {\ettl@lst@modif{#1}#3#2{#4}}% + (case 3/default 2)
+ {\ettl@lst@modif{#1}00{#4}}% ! (case 0)
+ {\ettl@lst@opt{#1}{#2}{#4}#5}% [ (option)
+ {\ettl@lst@opt{#1}{#2}{#4}[\do]}}% (default option)
+\long\def\ettl@lst@opt#1#2#3[#4]{%
+ \expandafter#1\expandafter{\number\ifnum#2=0 0\else\ifstrnum{#4}{1}{#2}\fi}{#3}[{#4}]}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{Macro}{breakloop}
+% \cs{breakloop} gobbles anything until the \CH{/End§List/} delimiter:
+% \begin{macrocode}
+\long\def\ettl@breakloop#1#2/End§List/{#1}
+\let\breakloop\ettl@breakloop
+% \end{macrocode}
+% \end{Macro}
+%
+%\begin{macro}{forloops}
+% In order to define for |\for|...|loop| macros, and to handle the case they are nested, we need a counter.
+% \begin{macrocode}
+\globcount\ettl@for@nested
+\long\def\ettl@forloop#1#2#3\do{%
+ \global\advance\ettl@for@nested\@ne\relax
+ \csdef{ettl@for@loop\the\ettl@for@nested}{%
+ #1\expandafter[\csname ettl@for@do\the\ettl@for@nested\endcsname]{#3}%
+ \csundef{ettl@for@do\the\ettl@for@nested}%
+ \csundef{ettl@for@loop\the\ettl@for@nested}%
+ \global\advance\ettl@for@nested\m@ne\relax}%
+ \expandafter\afterassignment\csname ettl@for@loop\the\ettl@for@nested\endcsname
+ \long\csdef{ettl@for@do\the\ettl@for@nested}#2%
+}% \ettl@for@nested
+% \end{macrocode}
+%\end{macro}
+%
+% \iffalse
+%<package>
+%<package>
+%<package>%% \csvloop[\command]\csvListMacro
+%<package>%% \csvloop*[\command]{item,item,item}
+% \fi
+%
+% \begin{Macro*}{csvloop}
+% Definition of |\csvloop|: \cs{forcsvloop} is also defined by \cmdref{DeclareCmdListParser} but is not purely expandable:
+%\begin{Macro}{forcsvloop}
+% \begin{macrocode}
+\DeclareCmdListParser\csvloop{,}
+% \end{macrocode}
+% \end{Macro}
+%\end{Macro*}
+%
+% \begin{codecomment}
+% \begin{Macro*}{listloop}
+%\begin{Macro}{forlistloop}
+% Definition of |\listloop| (with a `\,\textbar\,' of catcode 3 (math shift) -- cf.\xpackage{etoolbox}). \cs{forlistloop} is
+% defined by \cmdref{DeclareCmdListParser} but is not purely expandable:
+% \begin{macrocode}
+\begingroup\catcode`\|=3
+\DeclareCmdListParser\listloop{|}% global declaration
+\endgroup
+% \end{macrocode}
+% \end{Macro}
+%\end{Macro*}
+% \end{codecomment}
+%
+% \begin{codecomment}
+% \begin{Macro*}{toksloop}
+%\begin{Macro}{fortoksloop}
+% Definition of |\toksloop| (with no delimiter). \cs{fortoksloop} is defiined by \cmdref{DeclareCmdListParser} but is not
+% purely expandable:
+% \begin{macrocode}
+\DeclareCmdListParser\toksloop{}
+% \end{macrocode}
+%\end{Macro}
+% \end{Macro*}
+% \end{codecomment}
+%
+% \iffalse
+%<package>
+%<package>%% \forcsvloop\csvListMacro\do{...#1...}
+%<package>%% \forcsvloop*{item,item,item,...}\do{...#1...}
+% \fi
+%
+% \iffalse
+%<package>
+%<package>%% \csvlistadd \csvListMacro { item }
+%<package>%% \csvlist(g|e|x)add \csvListMacro { item }
+% \fi
+%
+%\begin{Macro*}{csvlistadd}
+%\begin{Macro*}{csvlistgadd}
+%\begin{Macro*}{csvlisteadd}
+%\begin{Macro}{csvlistxadd}
+% \begin{macrocode}
+\providerobustcmd\csvlistadd[2]{\ettl@nbk#2//{\appto#1{#2,}}{}//}
+\providerobustcmd\csvlistgadd[2]{\ettl@nbk#2//{\gappto#2{#2,}}{}//}
+\providerobustcmd\csvlisteadd[2]{\begingroup \protected@edef#1{#2}%
+ \expandafter\ettl@nbk#1//{\expandafter\endgroup
+ \expandafter\appto\expandafter#1\expandafter{#1,}}\endgroup//}
+\providerobustcmd\csvlistxadd[2]{\begingroup \protected@edef#1{#2}%
+ \expandafter\ettl@nbk#1//{\expandafter\endgroup
+ \expandafter\gappto\expandafter#1\expandafter{#1,}}\endgroup//}
+% \end{macrocode}
+%\end{Macro}
+%\end{Macro*}
+%\end{Macro*}
+%\end{Macro*}
+%
+% \iffalse
+%<package>
+%<package>%% \csvtolist [\ListMacro] \csvListMacro
+%<package>%% \csvtolist* [\ListMacro] {item,item,item}
+%<package>% Recommended use: \edef\ListMacro{\csvtolist{item,item,item}}
+% \fi
+%
+% \begin{Macro}{csvtolist}
+% This is the first application of |\csvloop|:
+% \begin{macrocode}
+\newcommand\csvtolist[1]{\FE@ifstar{#1}{\ettl@convertlist{{\csvloop*}\ettl@do@csvtolist}}
+ {\ettl@convertlist{\csvloop\ettl@do@csvtolist}}}
+\long\def\ettl@convertlist#1#2{\FE@testopt{#2}{\ettl@convert@list#1}{}}
+\long\def\ettl@convert@list#1#2[#3]#4{\ettl@nbk#3//%
+ {\edef#3{#1[#2]{#4}}}
+ {#1[#2]{#4}}//}
+\begingroup\catcode`\|=3% etb catcode
+\long\gdef\ettl@do@csvtolist#1{\unexpanded{#1}|}
+\endgroup
+% \end{macrocode}
+% \end{Macro}
+%
+% \iffalse
+%<package>
+%<package>%% \listtocsv [\csvListMacro] \ListMacro
+%<package>%% \listtocsv* [\csvListMacro] { expanded List }
+%<package>% Recommended use: \edef\csvListMacro{\listtocsv\ListMacro}
+% \fi
+%
+%\begin{Macro}{listtocsv}
+% This is the first application of |\listloop|:
+% \begin{macrocode}
+\newcommand\listtocsv[1]{\FE@ifstar{#1}{\ettl@convertlist{{\listloop*}\ettl@do@listtocsv}}
+ {\ettl@convertlist{\listloop\ettl@do@listtocsv}}}
+\long\def\ettl@do@listtocsv#1{\unexpanded{#1,}}
+% \end{macrocode}
+%\end{Macro}
+%
+% \iffalse
+%<package>%% \tokstolist [\ListMacro] { \toksListMacro / token token token }
+% \fi
+%
+% \begin{Macro}{tokstolist}
+% This is the first application of |\toksloop|:
+% \begin{macrocode}
+\newcommand\tokstolist[1]{\FE@ifstar{#1}{\ettl@convertlist{{\toksloop*}\ettl@do@tokstolist}}
+ {\ettl@convertlist{\toksloop\ettl@do@tokstolist}}}
+\begingroup\catcode`\|=3% etb catcode
+\long\gdef\ettl@do@tokstolist#1{\unexpanded{#1}|}
+\endgroup
+% \end{macrocode}
+% \end{Macro}
+%
+% \iffalse
+%<package>
+%<package>%% \csvtolistadd \ListMacro \csvListMacro
+%<package>%% \csvtolistadd* \ListMacro {item,item,item}
+% \fi
+% \begin{Macro}{csvtolistadd}
+% \cs{csvtolistadd} is not purely expandable:
+% \begin{macrocode}
+\newrobustcmd*\csvtolistadd{\@ifstar{\ettl@csvtolistadd*}{\ettl@csvtolistadd{}}}
+\long\def\ettl@csvtolistadd#1#2#3{\eappto#2{\csvtolist#1[]{#3}}}
+% \end{macrocode}
+% \end{Macro}
+%
+% \iffalse
+%<package>
+%<package>%% \tokstolistadd \ListMacro { \toksListMacro / token token token }
+% \fi
+%
+% \begin{Macro}{tokstolistadd}
+% \cs{tokstolistadd} is not purely expandable:
+% \begin{macrocode}
+\newrobustcmd*\tokstolistadd{\@ifstar{\ettl@tokstolistadd*}{\ettl@tokstolistadd{}}}
+\long\def\ettl@tokstolistadd#1#2#3{\eappto#2{\tokstolist#1[]{#3}}}
+% \end{macrocode}
+% \end{Macro}
+%
+%\begin{macro}{\ettl@RemoveInList} \cmdlabel{impl:ettl@RemoveInList}
+% This is the general constructor for deletion into lists with any separator:
+% \begin{macrocode}
+\newrobustcmd\ettl@RemoveInList[2]{\begingroup
+% #1 = \global #2 = macro name
+ \def\ettl@RemoveInList##1{%
+ \edef\ettl@RemoveInList####1####2{%
+ \ettl@Rem@veInList{####1}####2\noexpandcs{##1->remove}\noexpandcs{##1->result}%
+ }\ettl@RemoveInList{#1}#2%
+ }\expandafter\ettl@RemoveInList\expandafter{\romannumeral-`\q\@gobblescape#2}}
+\protected\long\def\ettl@Rem@veInList#1#2#3#4#5#6#7#8{%
+ \long\def#3[##1]##2#5#8#5##3##4/##5##6##7/End§List/{##6[##1+1]##2#5##3##4//##6##7/End§List/}%
+ \ifnotempty{#5}%% special case if no separator
+ {\long\def#4[##1]#5##2#5#5##3//##4/End§List/{\unexpanded{#1\def#7{##2#5}}%
+ \ettl@nbk#6//{\ettl@setresult 1of1>#6<{\number\numexpr##1-1\relax}}{}//}}%
+ {\long\def#4[##1]##2//##3/End§List/{\unexpanded{#1\def#7{##2}}%
+ \ettl@nbk#6//{\ettl@setresult 1of1>#6<{\number\numexpr##1-1\relax}}{}//}}%
+ \long\def#2##1{#3[0]#5##1#5#5#8#5//#3#4/End§List/}%
+ \edef#7{\endgroup\expandafter#2\expandafter{#7}}#7}
+\def\ettl@gobble@relax#1\relax{}
+% \end{macrocode}
+%\end{macro}
+%
+% \iffalse
+%<package>
+%<package>%% \listdel \listMacro { item }
+%<package>%% \listgdel \listMacro { item }
+%<package>%% \listedel \listMacro { item }
+%<package>%% \listxdel \listMacro { item }
+% \fi
+%
+% \begin{Macro*}{listdel}
+% \begin{Macro*}{listedel}
+% \begin{Macro*}{listgdel}
+% \begin{Macro}{listxdel}
+% \cs{listdel} removes an \prm{item} from a list, \cs{listedel} expands the \prm{item} (with |\protected@edef|) first,
+% \cs{listgdel} make the assignment to the (shorter-)list global and \cs{listxdel} both expands the \prm{item} and
+% makes the assignment global:
+% \begin{macrocode}
+\edef\ettl@restore@catcode{\catcode124 \the\catcode124}% |=124
+\catcode`\|=3
+\newrobustcmd\listdel[1][]{\ettl@RemoveInList{}\listdel|{#1}}
+\newrobustcmd\listgdel[1][]{\ettl@RemoveInList\global\listdel|{#1}}
+\newrobustcmd\listedel[1][]{\ettl@listedel{}\listdel|{#1}}
+\newrobustcmd\listxdel[1][]{\ettl@listedel\global\listdel|{#1}}
+\ettl@restore@catcode\undef\ettl@restore@catcode
+\newrobustcmd\ettl@listedel[6]{\begingroup\protected@edef#5{#6}\expandafter\endgroup
+ \expandafter\@swaparg\expandafter{#5}{\ettl@RemoveInList#1#2{#3}{#4}#5}}
+% \end{macrocode}
+% \end{Macro}
+% \end{Macro*}
+% \end{Macro*}
+% \end{Macro*}
+%
+% \iffalse
+%<package>
+%<package>%% \csvdel \listMacro { item }
+%<package>%% \csvgdel \listMacro { item }
+%<package>%% \csvedel \listMacro { item }
+%<package>%% \csvxdel \listMacro { item }
+% \fi
+%
+% \begin{Macro*}{csvdel}
+% \begin{Macro*}{csvedel}
+% \begin{Macro*}{csvgdel}
+% \begin{Macro}{csvxdel}
+% \cs{csvdel} removes an \prm{item} from a list, \cs{csvedel} expands the \prm{item} (with |\protected@edef|) first,
+% \cs{csvgdel} make the assignment to the (shorter-)list global and \cs{csvxdel} both expands the \prm{item} and
+% makes the assignment global:
+% \begin{macrocode}
+\newrobustcmd\csvdel[1][]{\ettl@RemoveInList{}\csvdel,{#1}}
+\newrobustcmd\csvgdel[1][]{\ettl@RemoveInList\global\csvdel,{#1}}
+\newrobustcmd\csvedel[1][]{\ettl@listedel{}\csvdel,{#1}}
+\newrobustcmd\csvxdel[1][]{\ettl@listedel\global\csvdel,{#1}}
+% \end{macrocode}
+% \end{Macro}
+% \end{Macro*}
+% \end{Macro*}
+% \end{Macro*}
+%
+% \iffalse
+%<package>
+%<package>%% \toksdel \listMacro { item }
+%<package>%% \toksgdel \listMacro { item }
+%<package>%% \toksedel \listMacro { item }
+%<package>%% \toksxdel \listMacro { item }
+% \fi
+%
+% \begin{Macro*}{toksdel}
+% \begin{Macro*}{toksedel}
+% \begin{Macro*}{toksgdel}
+% \begin{Macro}{toksxdel}
+% \cs{toksdel} removes an \prm{item} from a list, \cs{toksedel} expands the \prm{item} (with |\protected@edef|) first,
+% \cs{toksgdel} make the assignment to the (shorter-)list global and \cs{toksxdel} both expands the \prm{item} and
+% makes the assignment global:
+% \begin{macrocode}
+\newrobustcmd\toksdel[1][]{\ettl@RemoveInList{}\toksdel{}{#1}}
+\newrobustcmd\toksgdel[1][]{\ettl@RemoveInList\global\toksdel{}{#1}}
+\newrobustcmd\toksedel[1][]{\ettl@listedel{}\toksdel{}{#1}}
+\newrobustcmd\toksxdel[1][]{\ettl@listedel\global\toksdel{}{#1}}
+% \end{macrocode}
+% \end{Macro}
+% \end{Macro*}
+% \end{Macro*}
+% \end{Macro*}
+%
+%\iffalse
+%<package>
+%<package>
+%<package>%% \getlistindex[\indexmacro]{ \Listmacro }
+%<package>%% \getlistindex*[\indexmacro]{ expanded List }
+% \fi
+%
+% \begin{Macro}{getlistindex}
+% \cmd{getlistindex} may be defined, with its star form (no expansion of the list)
+% and normal form (\prm{Listmacro} expanded once);
+% The search-index is initialised at 1:
+%
+% We first need to get into a group where delimiter \CH{\textbar} and \CH{\&} have catcode 3:
+% \begin{macrocode}
+\newrobustcmd\ettl@getlistindex[6]{% #1=result, #2=\expandafter, #3=loop macro, #4=separator, #5=list of list macro, #6=item
+ \begingroup\long\def\ettl@getlistindex##1#4#6#4##2/End§List/{\endgroup
+ \ExpandAftercmds{\ettl@setresult 1of1>#1<}{\ettl@nbk##2//{#3*!{##1}}{-1}//}%
+ }#2\ettl@getlistindex#5#4#6#4/End§List/}
+\newrobustcmd\getlistindex{\@ifstar
+ {\@testopt{\ettl@get@listindex\relax}{}}
+ {\@testopt{\ettl@get@listindex\expandafter}{}}}
+\begingroup\catcode`\|=3% etb catcode
+\protected\long\gdef\ettl@get@listindex#1[#2]#3#4{%
+ \ifx#1\relax
+ \ettl@getlistindex{#2}{}\listloop|{#4}{#3}%
+ \else \ifiscs{#4}
+ {\ettl@getlistindex{#2}#1\listloop|{#4}{#3}}
+ {\ettl@getlistindex{#2}\listloop|{#4}{#3}}%
+ \fi}
+\endgroup%\catcode group
+% \end{macrocode}
+% \end{Macro}
+%
+% \iffalse
+%<package>
+%<package>%\getcsvlistindex [\result]{ item }{ csvlistmacro }
+%<package>%\getcsvlistindex*[\result]{ item }{ item,item,item }
+% \fi
+% \begin{Macro}{getcsvlistindex}
+% The command is robust, not purely expandable:
+% \begin{macrocode}
+\newrobustcmd\getcsvlistindex{\@ifstar
+ {\@testopt{\ettl@get@csvlistindex\relax}{}}
+ {\@testopt{\ettl@get@csvlistindex\expandafter}{}}}
+\protected\long\gdef\ettl@get@csvlistindex#1[#2]#3#4{%
+ \ifx#1\relax
+ \ettl@getlistindex{#2}{}\csvloop,{#4}{#3}%
+ \else \ifiscs{#4}
+ {\ettl@getlistindex{#2}#1\csvloop,{#4}{#3}}
+ {\ettl@getlistindex{#2}\csvloop,{#4}{#3}}%
+ \fi}
+% \end{macrocode}
+% \end{Macro}
+%
+% \begin{macro}{\ettl@ifinlist}
+% \cs{ettl@ifinlist} will build a \cs{ifinlist} macro for list with a given separator.
+% \begin{macrocode}
+\def\ettl@if@inlist#1#2{%#1=macro,#2=separator
+\newrobustcmd*#1{\@ifstar{\ettl@ifinlist{#2}{}}{\ettl@ifinlist{#2}\expandafter}}}
+\def\ettl@xif@inlist#1#2{%
+\newrobustcmd*#1{\@ifstar{\ettl@xifinlist{#2}{}}{\ettl@xifinlist{#2}\expandafter}}}
+\protected\long\def\ettl@ifinlist#1#2#3#4{\begingroup
+ \def\ettl@tempa##1#1##2#1/End§List/{\endgroup\ifnotblank{##2}%
+ }#2\ettl@tempa#2#1#3#1#4#1/End§List/}
+\protected\long\def\ettl@xifinlist#1#2#3#4{\begingroup
+ \protected@edef\ettl@tempa{\endgroup\ettl@ifinlist{#1}{#2}{#3}{#4}%
+ }\ettl@tempa}
+% \end{macrocode}
+% \end{macro}
+%
+% \iffalse
+%<package>
+%<package>
+%<package>%% \ifincsvlist{ item }{ csvlistmacro }{ true }{ false }
+%<package>%% \ifincsvlist*{ item }{ item,item,item,... }{ true }{ false }
+%<package>%% \xifincsvlist{ item }{ csvlistmacro }{ true }{ false }
+%<package>%% \xifincsvlist*{ item }{ item,item,item,... }{ true }{ false }
+% \fi
+%
+% \begin{Macro*}{ifincsvlist}
+% A robust command with a star form.
+% \begin{Macro}{xifincsvlist}
+% The same with |\protected@edef|.
+% \begin{macrocode}
+\ettl@if@inlist\ifincsvlist{,}
+\ettl@xif@inlist\xifincsvlist{,}
+\undef\ettl@if@inlist
+\undef\ettl@xif@inlist
+% \end{macrocode}
+% \end{Macro}
+% \end{Macro*}
+%
+% \iffalse
+%<package>
+%<package>%% \interval{ number }{ sorted comma separated list of numbers }
+% \fi
+%
+%\begin{Macro}{interval}
+% \cs{interval} will expand to the number of the interval of \prm{number} into the \prm{sorted comma separated list of integers}:
+% \begin{macrocode}
+\newcommand\interval[2]{\romannumeral-`\q%
+ \ExpandNext{\avoidvoid[\csvloop!{#2}]}{\csvloop+[\ettl@do@interval{#1}]{#2}}}
+\def\ettl@do@interval#1[#2]#3{\ifdim#1\p@<#3\p@ \@swap{\breakloop{#2}}\fi}
+% \end{macrocode}
+%\end{Macro}
+%
+% \iffalse
+%<package>
+%<package>%% \interplin{ number }{ sorted comma separated list of numbers }{ comma separated liist of numbers }
+% \fi
+%
+%\begin{Macro}{locinterplin}
+% \begin{macrocode}
+\newcommand\locinterplin[3]{\romannumeral-`\q
+ \unless\ifnum\numexpr(\csvloop!{#2})-(\csvloop!{#3})=0
+ \PackageError{etextools}{Using \string\locinterplin\space the lists in argument 1 and 2\MessageBreak
+ must have the same number of elements}
+ {You're in trouble here and I cannot proceed...}
+ \fi
+ \ExpandNextTwo{\ettl@locinterplin{#1}{#3}{#2}}{\interval{#1}{#2}}{\csvloop!{#2}}}
+\begingroup\catcode`\/ 12%
+\gdef\ettl@locinterplin#1#2#3#4#5{%
+ \ifnum#4=0 \csvloop[#4]{#2}%
+ \else\ifnum#4=#5 \expandafter\csvloop\expandafter[\number\numexpr#5-1]{#2}%
+ \else\ifdim#1\p@=\expandafter\csvloop\expandafter[\number\numexpr#4-1]{#3}\p@
+ \expandafter\csvloop\expandafter[\number\numexpr#4-1]{#2}%
+ \else\strip@pt\dimexpr%
+ \expandafter\csvloop\expandafter[\number\numexpr#4-1]{#2}\p@+%
+ (#1\p@-\expandafter\csvloop\expandafter[\number\numexpr#4-1]{#3}\p@)*%
+ (\expandafter\csvloop\expandafter[\number\numexpr#4-1]{#2}-\csvloop[#4]{#2})/%
+ (\expandafter\csvloop\expandafter[\number\numexpr#4-1]{#3}-\csvloop[#4]{#3})\relax
+ \fi\fi\fi}
+\endgroup% catcode group
+% \end{macrocode}
+%\end{Macro}
+%
+% \Subsection*{\thispackage package options (undocumented - not tested, not to be used)}
+%
+% \textsl{Undocumented option \xpackage{etoolbox}}.
+% \begin{macrocode}
+\DeclareOption{etoolbox}{%
+\renewcommand\ifblank[3]{\ettl@nbk #1//{#2}{#3}//}
+\renewcommand\ifdef[1]{\csname @\ifdefined#1first\else second\fi oftwo\endcsname}
+\renewcommand\ifcsdef[1]{\csname @\ifcsname#1\endcsname first\else second\fi oftwo\endcsname}
+\renewcommand\ifundef[1]{\csname @%
+ \ifdefined#1\ifx#1\relax first\else second\fi\else first\fi oftwo\endcsname}
+\renewcommand\ifcsundef[1]{\csname @%
+ \ifcsname#1\endcsname\expandafter\ifx\csname#1\endcsname\relax
+ first\else second\fi\else first\fi oftwo\endcsname}
+\edef\ifdefmacro#1{\unexpanded{\csname @%
+ \expandafter\ettl@ifdefmacro\meaning}#1\detokenize{macro:}/oftwo\endcsname}
+\edef\ettl@ifdefmacro{%
+ \def\noexpand\ettl@ifdefmacro##1\detokenize{macro:}##2/{\noexpand\ettl@nbk##2//{first}{second}//}%
+}\ettl@ifdefmacro
+\long\edef\ifcsmacro#1{\unexpanded{\csname @%
+ \expandafter\expandafter\expandafter\ettl@ifdefmacro\meaningcs}{#1}\detokenize{macro:}/oftwo\endcsname}
+\renewcommand\ifdefparam[1]{\csname @%
+ \ettl@expandaftwo\ettl@nbk\expandafter\ettl@params@meaning\meaning#1///{first}{second}//oftwo\endcsname}
+\renewcommand\ifcsparam[1]{\csname @%
+ \expandafter\expandafter\expandafter\ettl@nbk\parameters@meaningcs{#1}//{first}{second}//oftwo\endcsname}
+\renewcommand\ifnumcomp[3]{\csname @%
+ \ifnum\numexpr#1#2\numexpr#3 first\else second\fi oftwo\endcsname}
+}% etoolbox option - not to be used - experimental
+\ProcessOptions*\relax
+% \end{macrocode}
+%
+% \begin{macrocode}
+%</package>
+% \end{macrocode}
+%
+% \Section*{Examples} \refstepcounter{section}
+% \label{sec:examples}
+% ^^A\addcontentsline{toc}{section}{\texorpdfstring\dr{}\hskip\dimexpr\cftsecnumwidth-4pt Implementation}^^A do not add to .cmd file
+% \addcontentsline{toc}{section}{\protect\numberline{II}\cftsecfont Examples}^^A do not add to .cmd file
+% \addtocontents{toc}{\cftbeforesubsecskip=-2pt plus\gluestretch\cftbeforesubsecskip\relax}
+% ^^A\renewrobustcmd\noexpand\cftsubsecfont{\footnotesize}}\renewcommand\thesubsection{I.\arabic{subsection}}^^A for toc
+%
+% This is the code of \sty{etextools-example.tex} which comes with the package.
+%
+% \begin{macrocode}
+%<*example>
+\ProvidesFile{etextools-examples}
+\documentclass[11pt,french,a4paper,oneside]{scrartcl}
+\usepackage[latin1]{inputenc}
+\usepackage[T1]{fontenc}
+\usepackage[american]{babel}
+\usepackage{geometry,doc,ltxdockit,txfonts,fancyhdr,stmaryrd,graphicx,enumitem}
+\usepackage{etextools}
+%
+\usepackage{fancyvrb}
+%
+\makeatletter
+\let\org@newif\newif
+\def\newif#1{\ifx#1\ifnotempty\else\expandafter\org@newif\fi}
+\usepackage{umrand}
+\renewcommand\ifne[1]{\csname @\ifcat $\detokenize{#1}$first\else second\fi oftwo\endcsname\iffalse\iftrue}
+\let\newif\org@newif
+\font\umranda=umranda \def\Ch{\char'}
+%
+\def\textvb#1{{\usefont{T1}{txtt}{m}{n}#1}}
+\newrobustcmd\thispackage{\xpackage{\spot etextools}\xspace}
+\newrobustcmd\xpackage[1]{{\usefont{T1}{lmss}{bx}{n}\db\mbox{#1}}}
+\hypersetup{colorlinks,pdfstartview={FitH}}
+\geometry{top=1.5cm,bottom=1.2cm,left=2.5cm,right=1cm}
+\fancyhf{}
+\fancyhead[L]{Examples for the \thispackage package}
+\pagestyle{fancy}
+\DefineShortVerb{\|}
+\catcode`\^^a7 \active\def^^a7{\par\nobreak\vskip-\parskip}
+\DefineVerbatimEnvironment{VerbLines}{Verbatim}
+ {gobble=1,commandchars=!(),frame=lines,framesep=6pt,fontfamily=txtt,fontseries=m}
+\apptocmd\@list@extra{\parsep\parskip\topsep\z@\itemsep\z@}{}{}
+%
+\def\smex{\leavevmode\hb@xt@2em{\hfil$\longrightarrow$\hfil}}
+\def\FE{\setbox8\hbox{$\m@th\bindnasrepma$}%
+ \textcolor{fecc}{\scalebox{2}{$\copy8\mkern-13.5mu\copy8\mkern-13.5mu\copy8$}}}
+\def\pdfFE{\setbox8\hbox{$\m@th\bindnasrepma$}%
+ \textcolor{fecc}{\llap{\textsf{pdf}\TeX{}\,}\scalebox{2}{$\copy8\mkern-13.5mu\copy8\mkern-13.5mu\copy8$}}}
+\definecolor{fecc}{rgb}{.2,.6,.2}
+\definecolor{dg}{rgb}{0.00,0.37,0.00} \newrobustcmd\dg{\color{dg}} \newrobustcmd\dgbf{\dg\bfseries}
+\definecolor{spot}{rgb}{1.00,0.33,0.00} \newrobustcmd\spot{\color{spot}}
+\definecolor{db}{rgb}{0.00,0.00,0.25} \newrobustcmd\db{\color{db}}
+\newrobustcmd\blue{\color{blue}}
+\newrobustcmd\nnn{\normalfont\mdseries\upshape}
+%
+\newrobustcmd\ClearPage{\@ifstar\clearpage{}}
+\def\make@macro#1{\string\def\string#1\parameters@meaning#1\string{\strip@meaning#1\string}}
+\newcommand\preline{\@ifstar{\@preline}{\hrulefill\par\@preline}}
+\newcommand\@preline[2][1.5ex]{\noindent\hskip6pt\textvb{\make@macro#2}\par\ifblank{#1}{}{\vskip#1}}
+%
+\ifdef\pdfstrcmp{\let\ifpdfTeX\iffalse}{\let\ifpdfTeX\iftrue}
+%
+\newcommand*\test{\@ifstar{\let\fe\pdfFE\testi}{\let\fe\FE\testi}}
+\newcommand\testi[1]{%
+ \csname test#1\endcsname
+ \edef\usercmd{\strip@meaningcs{test#1}}\edef\result{\meaningcs{#1Test}}\noindent
+ \begin{tabular}{lp{15cm}}
+ \multicolumn{2}{l}{\textcolor{blue}{\llap{\fe\,\smex}\tt \usercmd}} \\[1.5ex]
+ \cmd{#1Test}= & \tt\bfseries\result
+ \end{tabular}\par\nobreak\hrulefill\null\goodbreak}
+%
+\begin{document}
+\title{\vskip-2cm\thispackage\ examples}
+\subtitle{Examples for some macros provided by the \thispackage package}
+\author{\small<FC -- December 12, 2010>}
+\date{}
+%
+\newsavebox\helpbox \newsavebox\helpboxx
+\newrobustcmd*\mydotleader[2][\z@]{\leavevmode\xleaders\hbox to\dimexpr1.7pt+#1{\hss\raise#2\hbox{$\scriptscriptstyle\cdotp$}\hss}}
+\begingroup\let\clearpage\@empty
+\setbox\helpbox\hbox to13cm{\hss\lower3cm\vbox to1.8cm{\maketitle\vss}\hss}
+\fboxsep\z@
+\newrobustcmd\corner[2][\spot\umranda]{\hbox{#1\rlap{\char'115}\char'#2}}
+\null\vskip-1cm\hskip-1cm\null\hfil\RandBox {\fbox{\copy\helpbox}}
+ font {\umranda} [0pt]
+ (\corner{17}) ([\Ch111]) (\corner{14})
+ ([\Ch112]) ([\Ch112])
+ (\corner{21}) ([\Ch111]) (\corner{11})
+\endgroup
+%
+\tableofcontents\hyperdef{ettlex}{toc}{}
+%
+\section{\cmd{expandnext} examples}
+%
+\subsection{Test if the replacement text of macro is really empty}
+%
+\def\xx{ }
+\def\testexpandnext{%
+ \edef\expandnextTest{\string\xx\ is \expandnext\ifempty{\xx}{}{not} empty}
+}
+\preline\xx
+\test{expandnext}
+%
+\def\xx{}
+\preline\xx
+\test{expandnext}
+%
+\ClearPage*
+\subsection{Test if the replacement text of a macro is blank (empty or spaces)}
+%
+\def\xx{something}
+\def\testexpandnext{%
+ \edef\expandnextTest{\string\xx\ is \expandnext\ifblank{\xx}{}{not} blank}
+}
+\preline\xx
+\test{expandnext}
+%
+\def\xx{ }
+\preline\xx
+\test{expandnext}
+%
+\section{\cmd{ExpandNext} examples}
+%
+Example of the main documentation file to reverse the order of the characters in a string:
+%
+\def\swap#1#2{{#2#1}} \def\do[#1]#2{\swap #2}% \do{abcdef} -> \swap ab + cdef -> {ba}cdef
+ % \do{{ba}cdef} -> \swap {ba}c + def -> {cba}def
+%
+\edef\result{\naturalloop[\do]{4}{12345}}
+\ExpandNext{\def\RESULT}{\naturalloop[\do]{4}{12345}}
+%
+\begin{VerbLines}
+\def\swap#1#2{{#2#1}} \def\do[#1]#2{\swap #2}
+\edef\result{\naturalloop[\do]{4}{12345}}
+\meaning\result = !bfseries!meaning!result
+\ExpandNext{\def\RESULT}{\naturalloop[\do]{4}{12345}}
+\meaning\RESULT = !bfseries!meaning!RESULT
+\end{VerbLines}
+%
+\subsection{Test the parameter string of a macro}
+%
+The following commands create the filter for the string: "\textvb{[\#1]\#2"}":^^a7
+\begin{VerbLines}[commandchars=!()]
+\ExpandNext{(!blue\DeclareStringFilter\ParaFilt)}
+ {\ExpandAftercmds\@gobblescape{\expandafter\string\csname(!blue[#1]#2)\endcsname}}
+\end{VerbLines}
+%
+\ExpandNext{\DeclareStringFilter\ParaFilt}
+ {\ExpandAftercmds\@gobblescape{\expandafter\string\csname[#1]#2\endcsname}}
+%
+\begin{enumerate}[label=\arabic*)~,noitemsep,nolistsep]
+\item |\csname[#1]#2\endcsname| is expanded first
+\item Immediately after: |\string|
+\item At this stage: |\[#1]#2| (everything in category code other) is no more expandable
+\item Then |\ExpandAftercmds| expands |\@gobblescape|
+\item |[#1]#2| is no more expandable
+\item Then |\ExpandNext| expands its first argument: |\DeclareStringFilter\ParaFilt{[#1]#2}|
+\end{enumerate}
+%
+Remark: |\detokenize| would have doubled the \# characters. Another possibility is to temporarily change the
+category code of \# to 12 (other):
+\begin{VerbLines}[commandchars=!()]
+\begingroup\catcode`\#=12
+ (!blue\DeclareStringFilter\ParaFilt{[#1]#2}) !nnn global declaration
+\endgroup
+\end{VerbLines}
+%
+\def\macroA#1#2{Something to do with #1 and #2}
+\def\macroB[#1]#2{Something to do with #1 and #2}
+%
+\preline[]\macroA
+\preline*[]\macroB
+\begin{Verbatim}[commandchars=!()]
+ !blue\ExpandNext{\ParaFilt=.}{\parameters@meaning\macroA}{macro complies with [\#1]\#2}
+ !blue{macro does not comply }
+\end{Verbatim}
+%
+\hfill\textvb{\dgbf\ExpandNext{\ParaFilt=.}{\parameters@meaning\macroA}{macro complies with [\#1]\#2}
+ {macro does not comply }}
+\begin{Verbatim}[commandchars=!()]
+ !blue\ExpandNext{\ParaFilt=.}{\parameters@meaning\macroB}{macro complies with [\#1]\#2}
+ !blue{macro does not comply }
+\end{Verbatim}
+\hfill\textvb{\dgbf\ExpandNext{\ParaFilt=.}{\parameters@meaning\macroB}{macro complies with [\#1]\#2}
+ {macro does not comply }}
+\par\hrulefill\par
+%
+\ClearPage*
+\section{Testing characters}
+\subsection{\cmd{ifsinglechar} versus \cmd{iffirstchar}}
+\def\testifsinglechar{%
+ \edef\ifsinglecharTest{\ifsinglechar *{*hello*}{ single star }{ something else }}
+}\hrulefill\par
+\test{ifsinglechar}
+%
+\def\testifsinglechar{%
+ \edef\ifsinglecharTest{\ifsinglechar *{ *}{ single star }{ something else }}
+}\hrulefill\par
+\test{ifsinglechar}
+%
+\def\testifsinglechar{%
+ \edef\ifsinglecharTest{\ifsinglechar *{ * }{ single star }{ something else }}
+}\hrulefill\par
+\test{ifsinglechar}
+{\small Note the space \textbf{after} the star $\uparrow$.}
+%
+\def\testiffirstchar{%
+ \edef\iffirstcharTest{\iffirstchar *{*hello*}{ first char is star }{ something else }}
+}\hrulefill\par
+\test{iffirstchar}
+%
+\subsection{Fully Expandable starred macros}
+\def\starmacro#1{\FE@ifstar{#1}\starred\notstarred}
+\def\starred#1{your "#1" will be processed by the STAR form}
+\def\notstarred#1{your "#1" will be processed by the NORMAL form}
+\def\testFE@ifstar{%
+ \edef\FE@ifstarTest{\starmacro{sample text}}}
+\preline\starmacro
+\preline*\starred
+\preline*\notstarred
+\test{FE@ifstar}
+%
+\def\testFE@ifstar{%
+ \edef\FE@ifstarTest{\starmacro*{sample text}}}
+\hrulefill\par
+\test{FE@ifstar}
+%
+\subsection{Fully Expandable macros with options}
+\def\optmacro#1{\FE@testopt{#1}\OPTmacro{Mr.}}
+\def\OPTmacro[#1]#2{#1 #2}
+\def\testFE@testopt{%
+ \edef\FE@testoptTest{\optmacro{Woody Allen}}}
+\preline\optmacro
+\preline*\OPTmacro
+\test{FE@testopt}
+%
+\def\testFE@testopt{%
+ \edef\FE@testoptTest{\optmacro[Ms.]{Vanessa Paradis}}}
+\hrulefill\par
+\test{FE@testopt}
+%
+\ClearPage*
+\section{Lists management}
+%
+\subsection{\cmd{csvloop} and \cmd{csvloop*} examples}
+%
+\subsubsection{\cmd{makequotes}}
+\def\makequotes#1{"#1"\space}
+\def\testcsvloop{%
+ \edef\csvloopTest{\csvloop*[\makequotes]{hello,world}}
+}
+\preline\makequotes
+\test{csvloop}
+%
+\subsubsection{\cmd{detokenize}}
+\def\testcsvloop{%
+ \edef\csvloopTest{\csvloop*[\detokenize]{\un,\deux}}
+}\hrulefill\par
+\test{csvloop}
+%
+\subsubsection{\cmd{numexpr}}
+\def\mylist{1,2,3,4,5}\def\BySeven#1{$#1\times 7 = \number\numexpr#1*7\relax$\par}
+\def\testcsvloop{%
+ \edef\csvloopTest{\csvloop[\BySeven]\mylist}}
+\preline\mylist
+\preline*\BySeven
+\test{csvloop}
+%
+\subsubsection{protected \cmd{textbf}}
+\def\testcsvloop{%
+ \protected@edef\csvloopTest{\csvloop*[\textbf]{hello ,my ,friends}}
+}\hrulefill\par
+\test{csvloop}
+%
+\subsection{Index in lists and items by index}
+%
+\subsubsection{\cmd{listloop}: getting specific item}
+\csvtolist*[\mylist]{one,two,three,four,five,alpha,beta,gamma}
+\def\testgetlistitem{%
+ \edef\getlistitemTest{\listloop[4]\mylist}
+}\hrulefill\par
+\noindent\hskip6pt|\csvtolist*[\mylist]{one,two,three,four,five,alpha,beta,gamma}|\par\vskip1.5ex
+\test{getlistitem}
+%
+\ClearPage*
+\subsubsection{\cmd{getlistindex}}
+\ifpdfTeX
+\leavevmode\vadjust{\textsl{Require the }\string\pdfstrcmp\ \textsl{primitive (pdf\TeX{}) :}}
+\def\testgetlistindex{%
+ \edef\getlistindexTest{\getlistindex{alpha}\mylist}
+}\hrulefill\par
+\noindent\hskip6pt|\csvtolist*[\mylist]{one,two,three,four,five,alpha,beta,gamma}|\par\vskip1.5ex
+\test*{getlistindex}
+%
+\leavevmode\vadjust{\textsl{Require the }\string\pdfstrcmp\ \textsl{primitive (pdf\TeX{}) :}}
+\def\testgetlistindex{%
+ \edef\getlistindexTest{\getcsvlistindex*{alpha}{one,two,three,four,five,alpha,beta}}
+}\hrulefill\par
+\test*{getlistindex}
+\fi
+\hrulefill\par
+%
+\getlistindex[\myindex]{alpha}\mylist
+{\color{blue}\noindent\hskip6pt\llap\smex|\getlistindex[\myindex]{alpha}\mylist|\par\vskip1.5ex}
+{\tt\string\myindex=\quad\textbf{\meaning\myindex}}
+\par\hrulefill\par\vskip.5ex
+%
+\hrulefill\par
+\newcount\myindex
+\getcsvlistindex*[\myindex]{alpha}{one,two,three,four,five,alpha,beta}
+\noindent\hskip6pt|\newcount\myindex|\par
+{\color{blue}\noindent\hskip6pt\llap\smex|\getcsvlistindex*[\myindex]{alpha}{one,two,three,four,five,alpha,beta}|}\par\vskip.5ex
+{\tt\string\the\string\myindex=\qquad\textbf{\the\myindex}}
+\par\hrulefill\par\vskip.5ex
+%
+\ClearPage
+\subsubsection{\cmd{gettokslistindex} with \cmd{ifcase}}
+%
+\hrulefill\par\vskip2ex\noindent
+\llap{\FE\,\smex}\par\vskip-2.5\baselineskip\strut
+\leavevmode\vadjust{Always purely expandable (no need of |\pdfstrcmp|, comparison done by |\ifx|):}
+\begin{Verbatim}
+ \ifcase \gettokslistindex{D}{LRDF\relax O}
+ What do to if L
+ \or What do to if R
+ \or What do to if D
+ \or What do to if F
+ \or What do to if \relax
+ \or What do to if O
+ \else Problem
+ \fi
+\end{Verbatim}
+%
+{\tt Result=\qquad\bfseries
+\ifcase\gettokslistindex{D}{LRDF}
+ What do to if L
+\or What do to if R
+\or What do to if D
+\or What do to if F
+\else Problem
+\fi}\par
+\hrulefill\par\vskip.5ex
+%
+\end{document}\endinput
+%</example>
+% \end{macrocode}
+%
+% \phantomsection
+% \Section*{Revision history}
+% \addcontentsline{toc}{section}{\texorpdfstring\dr{}\hskip\dimexpr\cftsecnumwidth-4pt Revision history}^^A not in .cmd file
+%
+% \begin{changelog}\footnotesize
+%
+% \begin{release}{3.1415926}{2010-12-07}
+% \item Addition of \cmdref{@char@testopt}
+% \item Correction of a but in \cmdref{ifempty} and \cmdref{ifnotempty}.
+% \item Correction (again...) in \cmdref{thefontname}: now use of \cs{nfss@text} (better if in math mode).
+% \item Documentation revisited with \Xpackage{interfaces}.
+% \end{release}
+%
+% \begin{release}{3.14159}{2010-04-20}
+% \item \cs{ettl@thefontname} overwrote \cs{T1/cmr/m/n/10} on the log file when the font \sty{ecmr1000} was used.\\
+% Fixed + modification of \cmdref{thefontname} in order to get both \TeX{} and \LaTeX{} font names.
+% \item Correction of bugs into \cmdref{listdel}
+% \item Joining the example file \sty{etextools-examples.tex} to this \sty{.dtx} file.
+% \end{release}
+%
+% \begin{release}{3.1415}{2009-10-14}
+% \item Correction of a bug in \cmdref{locinterplin}.
+% \end{release}
+%
+% \begin{release}{3.141}{2009-10-08}
+% \item |\relax| added after \cmdref{listloop}\stform! (\cmdref{csvloop}\stform! etc.) in order to explicitly stop |\numexpr|.
+% \end{release}
+%
+% \begin{release}{3.14}{2009-10-04}
+% \item Stabilisation of some commands.
+% \end{release}
+%
+% \begin{release}{3.0}{2009-09-09}
+% \item Definition of \cmdref{DeclareStringFilter}, \cmdref{FE@modifiers} and \cmdref{ettl@supergobble}
+%
+% \end{release}
+%
+% \begin{release}{2k}{2009-09-04}
+% \item Addition of \\
+% \cmdref{ExpandNext} \\
+% \cmdref{naturalloop} \\
+% the star form of \cmdref{futuredef} \\
+% the \cs{global} option of \cmdref{DeclareCmdListParser}
+% \item Reimplementation of \\
+% the lists macros for optimisation (cf \cmd{ettl@ifnotblank}) \\
+% \cmdref{ifsinglechar} for optimisation
+% \item Addition of examples to the \sty{etextools-examples.tex}
+% \item Test on pdf\LaTeX{} and Xe\TeX.
+% \end{release}
+%
+% \begin{release}{2i}{2009-08-31}
+% \item
+% Addition of \cmdref{futuredef} a macro (and vectorized) version of \cs{futurelet}.
+% \item
+% Redesign of \cmdref{expandnext}: the first argument can now be arbitrary code
+% (before, it was necessarily a single control sequence, as for \CS{expandafter}).
+% \item
+% Redesign of \cmdref{deblank}, after a solution provided by \xpackage{environ.sty}.
+% \item
+% Addition of \cmdref{ifincsvlist}, \cmdref{ifintokslist} and \cmdref{xifincsvlist}.
+% \item
+% Addition of \cmdref{forcsvloop}, \cmdref{forlistloop} and \cmdref{fortoksloop}.
+% \item
+% Addition of \cmdref{csvdel}, \cmd{csvedel}, \cmd{csvgdel} and \cmd{csvxdel}
+% \item
+% Optimization of \cmdref{getlistindex} and \cmdref{getcsvlistindex}
+% \end{release}
+%
+% \begin{release}{2t}{2009-08-15}
+% \item
+% Addition of \cmdref{ifnotempty}, \cmdref{ifstrcmp}, \cmdref{ifstrmatch}
+%
+% \end{release}
+%
+% \begin{release}{2h}{2009-08-14}
+% \item
+% \cmdref{getlistindex} is now fully expandable
+%
+% \item Addition of\\
+% \cmdref{toksloop}
+%
+% \item Addition of\\
+% \cmdref{FE@ifchar} as a generalization of \cmdref{FE@ifstar}.
+%
+% \end{release}
+%
+% \begin{release}{2z}{2009-08-12}
+% \item Addition of \\
+% \cmdref{ifempty}, \cmdref{toksloop}, \cmdref{tokstolist} and \cmdref{tokstolistadd}
+% \item
+% Modification of \cmdref{ifsinglechar}\\
+% \cmdref{ifsinglechar} now works with \cmdref{ifempty} so that:\\
+% \begin{tabbing}
+% \quad\=|\macro{ * }|\quad\= is no more considered as a starred form \\
+% \>\>because of the spaces following the |*| \\
+% \>\> however, the spaces \textbf{before} are skipped, \\
+% \>\>as does |\@ifnextchar| from the \LaTeX{} kernel.
+% \end{tabbing}
+%
+% \item
+% Index added to this documentation paper.
+% \end{release}
+
+% \begin{release}{2e}{2009-07-14}
+% \item
+% First version (include an example file)
+% \end{release}
+%
+% \end{changelog}
+%
+% \begin{thebibliography}{9}
+%
+% \bibitem{etex}
+% David Carlisle and Peter Breitenlohner
+% \textit{The \xpackage{etex} package};
+% 1998/03/26 v2.0;
+% \CTAN{macros/latex/contrib/etex-pkg/}.
+%
+% \bibitem{etoolbox}
+% Philipp Lehman
+% \textit{The \xpackage{etoolbox} package};
+% 2008/06/28 v1.7;
+% \CTAN{macros/latex/contrib/etoolbox/}.
+%
+% \end{thebibliography}
+%
+% \setcounter{IndexColumns}{2}\clearpage
+% \PrintIndex
+% \makeatletter
+% \immediate\write\@mainaux{\noexpand\newlabel{LastPage}{{}{\thepage}{}{page.\arabic{page}}{}}}
+% \Finale \ No newline at end of file
diff --git a/macros/latex/contrib/etextools/etextools.pdf b/macros/latex/contrib/etextools/etextools.pdf
new file mode 100644
index 0000000000..a8e2471e70
--- /dev/null
+++ b/macros/latex/contrib/etextools/etextools.pdf
Binary files differ