summaryrefslogtreecommitdiff
path: root/macros/generic/listofitems
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/generic/listofitems
Initial commit
Diffstat (limited to 'macros/generic/listofitems')
-rw-r--r--macros/generic/listofitems/README30
-rw-r--r--macros/generic/listofitems/listofitems-en.pdfbin0 -> 447840 bytes
-rw-r--r--macros/generic/listofitems/listofitems-en.tex590
-rw-r--r--macros/generic/listofitems/listofitems-fr.pdfbin0 -> 412514 bytes
-rw-r--r--macros/generic/listofitems/listofitems-fr.tex438
-rw-r--r--macros/generic/listofitems/listofitems.sty4
-rw-r--r--macros/generic/listofitems/listofitems.tex606
-rw-r--r--macros/generic/listofitems/listofitemsold.tex572
8 files changed, 2240 insertions, 0 deletions
diff --git a/macros/generic/listofitems/README b/macros/generic/listofitems/README
new file mode 100644
index 0000000000..12bd57f366
--- /dev/null
+++ b/macros/generic/listofitems/README
@@ -0,0 +1,30 @@
+___________________________________
+
+ The
+ listofitems
+ package
+
+ v1.63
+
+ 21/08/2019
+___________________________________
+
+Authors : Christian Tellechea, Steven B. Segletes
+Maintainer: Christian Tellechea
+E-mail : unbonpetit@netc.fr (CT)
+ steven.b.segletes.civ@mail.mil (SBS)
+ Comments, bug reports and suggestions are welcome.
+Licence : Released under the LaTeX Project Public License v1.3c or
+ later, see http://www.latex-project.org/lppl.txt
+
+----------------------------------------------------------------------
+
+Cette extension permet de capturer tous les \'el\'ements d'une liste
+dont le s\'eparateur a \'et\'e choisi par l'utilisateur et d'acc\'eder
+\`a tout \'el\'ement par une syntaxe simple.
+
+----------------------------------------------------------------------
+
+This package allows one to capture all the items of a list, for which
+the parsing character has been selected by the user, and to access any
+of these items with a simple syntax. \ No newline at end of file
diff --git a/macros/generic/listofitems/listofitems-en.pdf b/macros/generic/listofitems/listofitems-en.pdf
new file mode 100644
index 0000000000..018a8bdb6d
--- /dev/null
+++ b/macros/generic/listofitems/listofitems-en.pdf
Binary files differ
diff --git a/macros/generic/listofitems/listofitems-en.tex b/macros/generic/listofitems/listofitems-en.tex
new file mode 100644
index 0000000000..ca22711f26
--- /dev/null
+++ b/macros/generic/listofitems/listofitems-en.tex
@@ -0,0 +1,590 @@
+% This is the AMERICAN ENGLISH package documentation for "listofitems"
+\documentclass[american]{article}
+\usepackage[T1]{fontenc}
+\usepackage[utf8]{inputenc}
+\usepackage{listofitems,babel,xspace}
+\usepackage[bottom]{footmisc}
+\usepackage{libertine}\usepackage[italic]{mathastext}
+\usepackage[scaled=0.8]{luximono}
+\usepackage[margin=3cm]{geometry}
+\usepackage{fancybox}
+\usepackage{xcolor}
+\usepackage{listings,MnSymbol}
+\def\listofitems{\textsf{\loiname}\xspace}
+\def\eTeX{\hbox{$\varepsilon$-\TeX}}
+\makeatletter
+\def\code{\expandafter\code@i\string}
+\def\code@i#1{%
+ \begingroup
+ \par\nobreak\medskip\parindent0pt
+ \leftskip.1\linewidth
+ \catcode`\^^I 13 \begingroup\lccode`\~`\^^I \lowercase{\endgroup\def~{\leavevmode\space\space\space\space}}%
+ \let\do\@makeother \dospecials
+ \ttfamily\small\@noligs
+ \obeylines\obeyspaces
+ \def\code@ii##1#1{##1\par\medbreak\endgroup}%
+ \code@ii
+}
+\long\def\grab@toks#1\relax{\gdef\right@content{#1}}
+
+\newcommand\disable@lig[1]{%
+ \catcode`#1\active
+ \begingroup
+ \lccode`\~`#1\relax
+ \lowercase{\endgroup\def~{\leavevmode\kern\z@\string#1}}%
+}
+
+\newcommand\exemple[1][65]{%
+ \edef\par@@indent{\the\parindent}%
+ \par\nobreak\vskip5pt \noindent
+ \def\part@coeff{#1}%
+ \relax\leavevmode\null
+ \bgroup
+ \let\do\@makeother\dospecials
+ \catcode`\^^M\active \catcode`\ \active
+ \begingroup
+ \lccode`\~`\ \lowercase{\def~{ {}}}%
+ \lccode`\~`\^^M\lowercase{\endgroup\def~{\par\noexpand\leavevmode}}%
+ \@makeother:\disable@lig,\disable@lig-%
+ \exemple@@
+}
+
+\newcommand\exemple@@[1]{%
+ \def\@tempa##1#1{%
+ \xdef\left@content{##1}%
+ \egroup
+ \def\right@content{##1}%
+ \begingroup
+ \newlinechar`\^^M\everyeof{\relax}%
+ \expandafter\grab@toks\scantokens\expandafter{\right@content}%
+ \endgroup
+ \exemple@@@
+ }%
+ \@tempa
+}
+
+\begingroup
+\catcode`#=12
+\gdef\exemple@@@{%
+ \begingroup
+ \fboxsep1pt\relax
+ \edef\part@left{\the\dimexpr0.\part@coeff\linewidth-\fboxsep-\fboxrule}%
+ \edef\part@right{\the\dimexpr\linewidth-0.\part@coeff\linewidth-\fboxsep-\fboxrule}%
+ \fbox{%
+ \parbox[c]\part@left{\vskip5pt\relax\ttfamily\footnotesize\left@content\vskip5pt}%
+ \parbox[c]\part@right{\vskip5pt\relax\normalfont\footnotesize\right@content\vskip5pt}%
+ }%
+ \vskip7.5pt\relax
+ \endgroup
+}
+\endgroup
+\begingroup
+ \catcode`\<13 \catcode`\>13
+ \gdef\verb{\relax\ifmmode\hbox\else\leavevmode\null\fi
+ \bgroup
+ \verb@eol@error \let\do\@makeother \dospecials
+ \verbatim@font\@noligs
+ \catcode`\<13 \catcode`\>13 \def<{\begingroup$\langle$\itshape}\def>{$\rangle$\endgroup}%
+ \@ifstar\@sverb\@verb}
+\endgroup
+\makeatother
+% FOR AMERICAN-ENGLISH VERSION
+\usepackage{setspace}
+\setstretch{1.01}
+\usepackage{enumitem}
+\newcommand\no[1]{number #1}
+\let\bsc\textsc
+\def\americanloidate{\expandafter\americanloidatei\loidate/}
+\def\americanloidatei#1/#2/#3/{\number#3\relax\space\ifcase #2 \or January\or February\or March\or April\or May\or
+ June\or July\or August\or September\or October\or November\or December\fi{} #1}
+%\newcommand\flag[1]{\textcolor{red}{#1}}% DIAGNOSTIC FLAG FOR FURTHER TRANSLATION
+%\newcommand\cflag[1]{\textcolor{blue}{#1}}% DIAGNOSTIC FLAG FOR FURTHER TRANSLATION
+%
+\begin{document}
+\parindent=0pt
+\thispagestyle{empty}
+\begin{titlepage}
+ \renewcommand\thefootnote{\fnsymbol{footnote}}
+ \begingroup
+ \centering
+ \null\vskip.25\vsize
+ {\large\bfseries Package\par \Huge \listofitems\par}
+ \bigbreak
+ v\loiver
+ \smallbreak
+ \americanloidate
+ \vskip1.5cm
+ {Christian \bsc{Tellechea}\footnote{\texttt{unbonpetit@netc.fr}}\par Steven B. \bsc{Segletes}\footnote{steven.b.segletes.civ@mail.mil}}
+ \par
+ \endgroup
+ \vskip2cm
+ \leftskip=.2\linewidth \rightskip=.2\linewidth \small
+This simple package is designed to read a list of items whose
+ parsing separator may be selected by the user.
+Once the list is read, its items are stored in a structure that behaves
+ as a dimensioned array.
+As such, it becomes very easy to access an item
+ in the list by its number.
+For example, if the list is stored in the
+ macro \verb|\foo|, the item \no3 is designated by \verb|\foo[3]|.
+
+A component may, in turn, be a list with a parsing delimiter different from
+ the parent list, paving the way for
+ nesting and employing a syntax reminiscent of an array of
+ several dimensions of the type \verb|\foo[3,2]| to access the item \no2
+ of the list contained within the item \no3 of the top-tier list.
+\end{titlepage}
+\def\listofitems{\textsf\loiname\xspace}
+
+\section{Preface}
+\fbox{\vbox{\hsize\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax\textbf{Important}: As of version 1.62, \listofitems requires a \TeX{} engine that provides the \texttt{\string\expanded} primitive. If this is not available, an error message will be issued and version 1.61 will be loaded (last version working without the primitive \texttt{\string\expanded}); it is strongly recommended that you update your \LaTeX{} distribution in order to take advantage of the newer \TeX{} engines that provide for the use of this new primitive.}}\medbreak
+
+This package loads no external packages, must be used with the
+ \eTeX{} engine, and must be called in (pdf)\hskip0pt(Xe)\hskip0pt(lua)\LaTeX{} with
+ the invocation
+\code|\usepackage{listofitems}|
+
+and under (pdf)(Xe)(Lua)\TeX {} by way of
+\code|\input listofitems.tex|
+
+\section{Read a Simple List}
+\paragraph{Set the parsing separator}
+The default parsing separator is the comma and if we want change it, we must do so
+ before reading a list of items, with the definition
+ \verb|\setsepchar{<parsing-separator>}|.
+A \verb|<parsing-separator>| is a set of tokens which possess catcodes different from
+ 1 and 2 (the opening and closing braces), 14 (usually
+ \verb|%|) and 15.
+The token of catcode 6 (usually \verb|#|) is accepted only if it
+ is followed by an integer, denoting the argument of a macro;
+In no case should this token be provided alone as the \verb|<parsing-separator>|.
+Commands can be included in this set of tokens,
+including the \TeX{} primitive \verb|\par|.%
+\smallbreak
+The parsing-separator \verb|<delimiter>| ``\verb-/-'' is reserved by default
+ for nested lists (see page 3). %\ref{nested.list.delimiters}).
+It is therefore not proper to write "\verb-\setsepchar{/}-"
+ because the \listofitems{} package would misunderstand that you want to read
+ a nested list.
+To set ``\verb-/-'' as the \verb|<parsing-separator>| for a simple list,
+ it is necessary, using the optional argument, to choose
+ a different parsing-separator \verb|<delimiter>| for nested lists,
+ for example ``\verb|.|'', and write ``\verb+\setsepchar[.]{/}+''.
+\medbreak
+
+It is not possible to select \verb-|- as the \verb|<delimiter>| because it would
+ conflict with the logical \textbf{OR}, denoted ``\verb-||-'' (see below).
+However, one can work around this limitation, at one's own peril, writing
+ ``\verb-\setsepchar{{|}}-''.
+
+\paragraph{Read a list}
+To read the list of items, the \verb|\readlist<macro-list>{<list>}| should be called.
+In so doing, the \verb|<list>| is read and the items are stored in a macro, denoted
+ \verb|<macro-list>| which therefore acts as a table with the items of the
+ \verb|<list>|.
+If braces appear as part of a list item, they
+ \emph{must} be balanced.
+Tokens possessing the catcodes 6, 14 and 15 are not allowed in the lists.
+
+For example, to set the \verb|<macro-list>| named \verb|\foo|, we can write
+\code|\setsepchar{,}
+\readlist\foo{12,abc, x y ,{\bfseries z}, ,\TeX,,!}|
+\setsepchar{,}
+\readlist\foo{12,abc, x y ,{\bfseries z}, ,\TeX,,!}
+
+If the \verb|<list>| is contained in a macro, then this macro is expanded.
+Therefore, we can simply employ the syntax
+ \verb|\readlist<macro-list><macro>|
+as in
+
+\code|\setsepchar{,}
+\def\List{12,abc, x y ,{\bfseries z}, ,\TeX,,!}
+\readlist\foo\List|
+
+The macro \verb|\greadlist| makes \emph{global} assignments and therefore, enables the use of \verb|<macro-list>| outside of the group where \verb|\greadlist| has been executed.
+
+\paragraph{Access an item}
+The macro \verb|\foo| \emph{requires} a numeric argument in square brackets,
+ which we symbolically denote as $i$, indicating the rank of the item
+ you wish to access.
+So \verb|\foo[1]| is\footnote{\texttt{\textbackslash
+ foo[}$i$\texttt] requires 2 expansions to give the item.} ``\verb|12|''. Similarly, \verb|\foo[4]| is
+ ``\verb|{\bfseries z}|''.
+
+The number $i$ can also be negative in which case the counting is done from the end
+ of the list: $-1$ represents the last item, $-2$ the penultimate, etc.
+If the number of items is $n$, then the argument $-n$ is the first item.
+\medbreak
+
+In general, if a \verb|<list>| has a length $n$, then the index $i$ can be in the
+ interval $[1\,;n]$ or $[-n\,;-1]$.
+Otherwise, a compilation error occurs.
+
+If the index is empty, \verb|\foo[]| produces the complete \verb|<list>|.
+
+The macro \verb|\foosep| is created. It is used with the syntax
+ \verb|\foosep[<index>]| and allows access to the parsing-separator that follows the
+ item of rank \verb|<index>|.
+The last parsing-separator (the one following the last item) is empty.
+If the \verb|<index>| is empty, \verb|\foosep[]| is empty.
+
+\paragraph{Select several possible parsing separators}
+To specify several possible separators, use the \textbf{OR} operator,
+ denoted ``\verb-||-''.
+One can use this feature, for example, to isolate the terms in an
+ algebraic sum:
+
+\exemple/\setsepchar{+||-}
+\readlist\term{17-8+4-11}
+1) \term[1] (parsing separator = \termsep[1])\par
+2) \term[2] (parsing separator = \termsep[2])\par
+3) \term[3] (parsing separator = \termsep[3])\par
+4) \term[4] (parsing separator = \termsep[4])/
+
+\paragraph{Number of items}
+If we write \verb|\readlist<macro-list>{<list>}|, then the macro \verb|<macro-list>len|
+ con\-tains\footnote{That is to say, it is
+ purely expandable and grows into a number.}
+ the number of the items in \verb|<list>|.
+In the example with \verb|\foo|, the macro \verb|\foolen| expands to \foolen.
+
+\paragraph{View all items}
+For purposes of debugging, the macro \verb|\showitems<macro-list>| includes all
+ items from a list, while the star version displays these items ``detokenized.''
+ \footnote{The primitive \texttt{\string\detokenize}, conducting this
+ decomposition, inserts a space after each control sequence.}
+
+\exemple/\showitems\foo\par
+\showitems*\foo/
+
+The presentation of each list item is assigned to the macro \verb|\showitemsmacro|
+ whose code is
+
+\code|\newcommand\showitemsmacro[1]{%
+ \begingroup\fboxsep=0.25pt \fboxrule=0.5pt \fbox{\strut#1}\endgroup
+ \hskip0.25em\relax}|
+
+It is therefore possible ---~and desirable~--- to redefine it if we desire a
+ different presentation effect.\medbreak
+
+The macro \verb|\fbox| and associated dimensions \verb|\fboxsep| and
+ \verb|\fboxrule|, are defined by \listofitems, when \textit{not}
+ compiled under \LaTeX{}, to achieve the same result \textit{as if}
+ performed under \LaTeX.
+
+\paragraph{Suppression of extreme (leading/trailing) spaces}
+By default, \listofitems reads and retains the spaces located at
+ the beginning and end of an item.
+For these spaces to be ignored when reading the \verb|<list>|, execute the starred
+ version \verb|\readlist*<macro>{<list>}|:
+
+\exemple|\setsepchar{,}
+\readlist*\foo{12,abc, x y ,{\bfseries z}, ,\TeX,,!}
+\showitems\foo|
+
+\paragraph{Managing empty items}
+By default, the \listofitems package retains and accounts for empty items.
+Thus, in the previous ex\-am\-ple, the 2nd expansion of \verb|\foo[7]| is empty.
+For empty items of the list (i.e., those list items defined by two
+ consecutive parsing delimiters) to be ignored, we must,
+ before invoking \verb|\readlist|,
+ execute the macro \verb|\ignoreemptyitems| .
+To return to the default package behavior, simply execute the macro
+ \verb|\reademptyitems|.
+
+This option can be used alone or in combination with \verb|\readlist*|,
+ in which case the suppression of extreme (leading/trailing) spaces occurs
+ \textit{before} \textsf{listofitems} ignores the empty list items:
+
+\exemple|\setsepchar{,}
+\ignoreemptyitems
+\readlist\foo{12,abc, x y ,{\bfseries z}, ,\TeX,,!}
+a) number of items = \foolen\par
+ \showitems\foo
+
+\readlist*\foo{12,abc, x y ,{\bfseries z}, ,\TeX,,!}
+b) number of items = \foolen\par
+ \showitems\foo|
+
+\paragraph{Iterate over a list}
+Once a list read by \verb|\readlist| and stored in a \verb|<macro-list>|, one may
+ iterate over the list with the syntax
+ \verb|\foreachitem <variable> \in <macro-list>{<code>}|:
+The \verb|<variable>| is a macro chosen by the user that will loop over the value
+ of each item in the list.
+
+The macro \verb|<variable>cnt| represents the sequence number of the item in
+ \verb|<variable>|.
+
+\exemple|\setsepchar{ }% parsing-separator = space
+\readlist\phrase{One phrase to test.}
+\foreachitem\word\in\phrase{List item number \wordcnt{}: \word\par}|
+
+\paragraph{Assign an item to a macro}
+The \verb|\itemtomacro<macro-list>[index]<macro>| assigns to the \verb|<macro>|
+ the item designated by \verb|<macro-list>[index]|.
+The \verb|<macro>| thus defined is purely expandable provided that the tokens
+ in the items are expandable.
+
+\exemple|\setsepchar{ }% parsing-separator = space
+\readlist\phrase{One phrase to test.}
+\itemtomacro\phrase[2]\aword
+\meaning\aword\par
+\itemtomacro\phrase[-1]\wordattheend
+\meaning\wordattheend|
+
+\section{Nested Lists}
+We speak of a list being ``nested'' when asking \listofitems to read a list where
+ the items are, in turn, understood as being a list (implying a parsing
+ separator different from the top-tier list).
+The nesting depth is not limited, but in practice, a depth of
+ 2 or 3 will usually suffice.
+
+\paragraph{Defining the parsing separators}\label{nested.list.delimiters}
+To indicate that a list will be nested, so that
+ the list parsing will be performed recursively, one must specify multiple
+ parsing separators, each corresponding to the particular tier of nesting.
+This list of parsing separators is itself given as a delimited list to
+ the macro \verb|\setsepchar|, with the syntax
+ \verb|\setsepchar[<delimiter>]{<delimited-list-of-parsing-separators>}|.
+
+By default, the \verb|<delimiter>| is ``\texttt{/}''.
+Thus, writing
+
+\code|\setsepchar{\\/,/ }|
+
+indicates a recursive depth of 3, with the parsing-separator list delimiter defaulting
+ to ``\texttt{/}'':
+
+\begin{itemize}[itemsep=0pt,topsep=0pt,partopsep=0pt,parsep=0pt,label=---]
+ \item Tier 1 items are parsed between ``\verb|\\|'' delimiters;
+ \item Tier 2 items are found within Tier 1 items, parsed between ``\verb|,|'' delimiters;
+ \item finally, the Tier 3 items are found within Tier 2 items, parsed between the
+ ``\verb*| |'' delimiters.
+\end{itemize}
+
+The \verb|<depth>| of nesting is contained in the purely expandable macro \verb|\nestdepth|.
+
+\paragraph{Read and access list items}
+For nested lists, the use of
+ indices obey the following rules:
+
+\begin{itemize}[itemsep=0pt,topsep=0pt,partopsep=0pt,parsep=0pt,label=---]
+ \item \verb|[]| is the main list, i.e., the argument of \verb|\readlist|;
+ \item \verb|[<i>]| means the item \no\verb|<i>| of the main list;
+ \item \verb|[<i>,<j>]| means the item \no\verb|<j>| of the list
+ mentioned in the previous point (a subitem);
+ \item \verb|[<i>,<j>,<k>]| means the item \no\verb|<k>| of the
+ list mentioned in the previous point (a sub-subitem);
+ \item etc.
+\end{itemize}
+
+As in the case of a non-nested list, the index may be negative.
+
+To read items, the syntax of \verb|\readlist| is exactly the same as
+ that for simple (non-nested) lists:
+
+\exemple|\setsepchar{\\/,/ }
+\readlist\baz{1,2 a b,3 c\\4 d e f,5,6\\7,,8, ,9 xy z}
+a) \string\baz[1] is \baz[1]\par
+b) \string\baz[1,1] is \baz[1,1]\par
+c) \string\baz[1,1,1] is \baz[1,1,1]\par
+b) \string\bar[1,2] is \baz[1,2]\par
+e) \string\baz[1,2,3] is \baz[1,2,3]\par
+f) \string\baz[-2,1,-1] is \baz[-2,1,-1]|
+
+\paragraph{The operator ``||''}
+This operator may be employed at any level of nesting.
+
+\exemple=\setsepchar[,]{+||-,*||/}
+\readlist\numbers{1+2*3-4/5*6}
+Term 1: \numbers[1]\par
+Term 2: \numbers[2] (factors: \numbers[2,1] and
+ \numbers[2,2])\par
+Term 3: \numbers[3] (factors: \numbers[3,1],
+ \numbers[3,2] and \numbers[3,3])=
+
+\paragraph{Number of list items}
+The macro \verb|\listlen<macro-list>[<index>]| requires 2 expansions
+ in order to
+ give the number of items in the list specified by the \verb|<index>|.
+The \verb|<depth>| of the \verb|<index>| must be strictly less than that
+ of the list.
+
+For the case where the \verb|<index>| is empty,
+ \verb|\listlen<macro-list>[]|, with 2 expansions, yields the identical result
+ as \verb|<macro-list>len| with 1 expansion.
+
+\exemple|\setsepchar{\\/,/ }
+\readlist\baz{1,2 a b,3 c\\4 d e f,5,6\\7,,8, ,9 xy z}
+a) \bazlen\ or \listlen\baz[]\par
+b) \listlen\baz[1]\par
+c) \listlen\baz[2]\par
+d) \listlen\baz[3]\par
+e) \listlen\baz[3,1]\par
+f) \listlen\baz[3,4]\par% 2 empty items
+g) \listlen\baz[3,5]|
+
+\paragraph{Displaying list items}
+The macro \verb|\showitems<macrolist>[<index>]| displays items from the list specified by
+ \verb|<index>|, in the same manner as \verb|\listlen|.
+The \verb|<depth>| of the \verb|<index>| must be strictly less than
+ that of the \verb|<list>|.
+
+\exemple|\setsepchar{\\/,/ }
+\readlist\baz{1,2 a b,3 c\\4 d e f,5,6\\7,,8, ,9 xy z}
+a) \showitems\baz[]\par
+b) \showitems\baz[1]\par
+c) \showitems\baz[2]\par
+d) \showitems\baz[3]\par
+e) \showitems\baz[3,1]\par
+f) \showitems\baz[3,4]\par% 2 empty items
+g) \showitems\baz[3,5]|
+
+
+
+\paragraph{Empty items and extreme (leading/trailing) spaces}
+The removal of empty items and/or leading/\allowbreak trailing spaces will occur in \emph{all}
+ the items, regardless of the degree of nesting.
+It is clear that a space, ``\verb*| |'', is useless as a parsing separator if you want
+ to use \verb|\readlist*|.
+Therefore, in the following example, ``\verb|*|'' is instead selected as the (3rd-tier)
+ parsing separator.
+
+Further, we remove only the extreme spaces, but retain empty items.
+
+\exemple|\setsepchar{\\/,/*}
+\readlist*\baz{1, 2*a*b ,3*c\\4*d*e*f,5,6\\7,,8, ,9* xy *z}
+a) \showitems\baz[]\par
+b) \showitems\baz[1]\par
+c) \showitems\baz[2]\par
+d) \showitems\baz[3]\par
+e) \showitems\baz[3,1]\par
+f) \showitems\baz[3,4]\par
+g) \showitems\baz[3,5]% "xy" without extreme spaces|
+
+\paragraph{Iterate over a list}
+The syntax \verb|\foreachitem <variable> \in <macro>[<index>]{<code>}|
+ remains valid where now the \verb|<index>| specifies the item
+ (understood as a list) on which to iterate.
+The \verb|<depth>| of the \verb|<index>| must be strictly less than
+ that of the \verb|<list>|.
+
+
+\paragraph{Assign an item to a macro}
+The syntax \verb|\itemtomacro<macro-list>[<index>]<macro>| remains valid to assign
+ to \verb|<macro>| the item specified by \verb|<macro-list>[<index>]|.
+
+\exemple[55]|\setsepchar[,]{\\, }
+\readlist\poem{There once was a runner named Dwight\\%
+Who could speed even faster than light.\\%
+He set out one day\\%
+In a relative way\\%
+And returned on the previous night.}
+\itemtomacro\poem[2]\verse
+2nd verse = \verse
+
+\itemtomacro\poem[2,-4]\word
+A word = \word|
+
+The macro \verb|\gitemtomacro| makes a global assignment.
+
+\section{Balanced Tokens}
+
+For the parsing of items, it is possible, with version 1.6, to take into
+ account the presence of \emph{balanced tokens}.
+Thus, if a list of paired tokens is defined, then each parsed item
+ in the list will extend to the first \verb|<separator>|, while assuring
+ that any paired tokens are balanced (i.e., occur in matched pairs within
+ the item).
+
+To define a list of balanced-token pairs, we use
+
+\code|\defpair{<tok1><tok2><tok3><tok4>...}|
+
+where the token list is read in pairs to form each matched-token pair.
+A \verb|<token>| that serves within a matched pair must consist of
+ a single character---%
+macros, primitives, spaces, braces, the token
+ "\verb|#|", as well as sets of several-tokens-between-%
+ braces are all forbidden.
+The two tokens which form a pair \emph{must} be different from
+ each other.
+
+\exemple/\setsepchar{+||-}
+\defpair{()[]}
+\readlist\terms{1+2*[3+4*(5+6-7)+8]-9+10}
+\showitems\terms/
+
+To return to the package's default behavior, that is, without
+ paired tokens, you must execute
+
+\code|\defpair{}|
+
+In an expression, in order to store in a macro that which
+ is between two matched tokens, we can call on
+
+\code|\insidepair<tok1><tok2>{<expression>}\macro|
+
+which will put in the \verb|\macro| that which lies between the pair
+ \verb|<tok1><tok2>| in the \verb|<expression>|.
+
+\exemple/\setsepchar{+||-}
+\defpair{()}
+\readlist\terms{1+2*(3+4*(5+6-7)+8)-9+10}
+\showitems\terms
+
+\itemtomacro\terms[2]\parenterm
+In the outer parenthesis:
+\insidepair()\parenterm\inbigparen
+"\inbigparen"
+
+In the inner parenthesis:
+\insidepair()\inbigparen\insmallparen
+"\insmallparen"/
+
+\section{The Code}
+
+Any suggestion, bug report, remark, request, addition or modification
+ of functionality is welcome; in this case, I invite users of
+ \listofitems to send me an email to \verb|unbonpetit@netc.fr|.\medbreak
+
+The code below is the exact verbatim of the file \verb|listofitems.tex|.
+I hope that the few comments scattered throughout it will
+ be enough for the user or the curious to understand the internal
+ machinery of this package:
+
+
+\lstinputlisting[
+ language=TeX,
+ inputencoding=latin1,
+ moretexcs={unless,ifcsname,ifdefined,detokenize,numexpr,dimexpr,glueexpr,unexpanded,expanded},
+ basicstyle=\small\ttfamily\color{black!25},
+ identifierstyle=\bfseries\color{white},%
+ backgroundcolor=\color{black!85},
+ keywordstyle=\bfseries\color{orange},
+ commentstyle=\color{cyan!66},
+ columns=fixed,
+ alsoletter={\_},
+ tabsize=2,
+ extendedchars=true,
+ showspaces=false,
+ showstringspaces=false,
+ numbers=left,
+ numberstyle=\tiny\ttfamily\color{black},
+ breaklines=true,
+ prebreak={\hbox{$\rhookswarrow$}},
+ breakindent=3em,
+ breakautoindent=true,
+ xleftmargin=1em,
+ xrightmargin=0pt,
+ lineskip=0pt,
+ numbersep=1em,
+ classoffset=1,
+ alsoletter={\_},
+ morekeywords={defpair,insidepair,setsepchar,greadlist,readlist,listlen,foreachitem,%
+ showitems,showitemsmacro,itemtomacro,gitemtomacro,ignoreemptyitems,reademptyitems},
+ keywordstyle=\bfseries\color{red!85!black},
+ classoffset=0,
+ ]{listofitems.tex}
+\end{document} \ No newline at end of file
diff --git a/macros/generic/listofitems/listofitems-fr.pdf b/macros/generic/listofitems/listofitems-fr.pdf
new file mode 100644
index 0000000000..6cf2128a85
--- /dev/null
+++ b/macros/generic/listofitems/listofitems-fr.pdf
Binary files differ
diff --git a/macros/generic/listofitems/listofitems-fr.tex b/macros/generic/listofitems/listofitems-fr.tex
new file mode 100644
index 0000000000..8eaff849df
--- /dev/null
+++ b/macros/generic/listofitems/listofitems-fr.tex
@@ -0,0 +1,438 @@
+% !TeX encoding = UTF-8
+% Ceci est la documentation du package "listofitems"
+%
+% Fichier compilé avec pdflatex
+\documentclass[french,a4paper]{article}
+\usepackage[utf8]{inputenc}
+\usepackage[T1]{fontenc}
+\usepackage{listofitems,babel}
+\usepackage[bottom]{footmisc}
+\usepackage{libertine}\usepackage[italic,frenchmath]{mathastext}
+\usepackage[scaled=0.8]{luximono}
+\usepackage[margin=3cm]{geometry}
+\usepackage{fancybox,xcolor,xspace,listings,MnSymbol}
+\def\listofitems{\loiname\xspace}
+\def\eTeX{\hbox{$\varepsilon$-\TeX}}
+\makeatletter
+\def\code{\expandafter\code@i\string}
+\def\code@i#1{%
+ \begingroup
+ \par\nobreak\medskip\parindent0pt
+ \leftskip.1\linewidth
+ \catcode`\^^I 13 \begingroup\lccode`\~`\^^I \lowercase{\endgroup\def~{\leavevmode\space\space\space\space}}%
+ \let\do\@makeother \dospecials
+ \ttfamily\small\@noligs
+ \obeylines\obeyspaces
+ \catcode`\<13 \catcode`\>13
+ \begingroup\lccode`\~`\<\lowercase{\endgroup\def~{\begingroup$\langle$\itshape}}%
+ \begingroup\lccode`\~`\>\lowercase{\endgroup\def~{\/$\rangle$\endgroup}}%
+ \def\code@ii##1#1{##1\par\medbreak\endgroup}%
+ \code@ii
+}
+\long\def\grab@toks#1\relax{\gdef\right@content{#1}}
+
+\newcommand\disable@lig[1]{%
+ \catcode`#1\active
+ \begingroup
+ \lccode`\~`#1\relax
+ \lowercase{\endgroup\def~{\leavevmode\kern\z@\string#1}}%
+}
+
+\newcommand\exemple[1][60]{%
+ \edef\par@@indent{\the\parindent}%
+ \par\nobreak\vskip5pt \noindent
+ \def\part@coeff{#1}%
+ \relax\leavevmode\null
+ \bgroup
+ \let\do\@makeother\dospecials
+ \catcode`\^^M\active \catcode`\ \active
+ \begingroup
+ \lccode`\~`\ \lowercase{\def~{ {}}}%
+ \lccode`\~`\^^M\lowercase{\endgroup\def~{\par\noexpand\leavevmode}}%
+ \@makeother:\disable@lig,\disable@lig-%
+ \exemple@@
+}
+
+\newcommand\exemple@@[1]{%
+ \def\@tempa##1#1{%
+ \xdef\left@content{##1}%
+ \egroup
+ \def\right@content{##1}%
+ \begingroup
+ \newlinechar`\^^M\everyeof{\relax}%
+ \expandafter\grab@toks\scantokens\expandafter{\right@content}%
+ \endgroup
+ \exemple@@@
+ }%
+ \@tempa
+}
+
+\begingroup
+\catcode`#=12
+\gdef\exemple@@@{%
+ \begingroup
+ \fboxsep1pt\relax
+ \edef\part@left{\the\dimexpr0.\part@coeff\linewidth-\fboxsep-\fboxrule}%
+ \edef\part@right{\the\dimexpr\linewidth-0.\part@coeff\linewidth-\fboxsep-\fboxrule}%
+ \fbox{%
+ \parbox[c]\part@left{\vskip5pt\relax\ttfamily\footnotesize\left@content\vskip5pt}%
+ \parbox[c]\part@right{\vskip5pt\relax\normalfont\footnotesize\right@content\vskip5pt}%
+ }%
+ \vskip7.5pt\relax
+ \endgroup
+}
+\endgroup
+\begingroup
+ \catcode`\<13 \catcode`\>13
+ \gdef\verb{\relax\ifmmode\hbox\else\leavevmode\null\fi
+ \bgroup
+ \verb@eol@error \let\do\@makeother \dospecials
+ \verbatim@font\@noligs
+ \catcode`\<13 \catcode`\>13 \def<{\begingroup$\langle$\itshape}\def>{$\rangle$\endgroup}%
+ \@ifstar\@sverb\@verb}
+\endgroup
+\def\longfrloidate@i#1/#2/#3\@nil{\number#3\relax\ifnum#3=1 \ier\fi\space \ifcase #2 \or janvier\or février\or mars\or avril\or mai\or juin\or juillet\or aout\or septembre\or octobre\or novembre\or décembre\fi\space#1}
+\def\longfrloidate{\expandafter\longfrloidate@i\loidate\@nil}
+\makeatother
+\begin{document}
+\parindent=0pt
+\thispagestyle{empty}
+\begin{titlepage}
+ \renewcommand\thefootnote{\fnsymbol{footnote}}
+ \begingroup
+ \centering
+ \null\vskip.25\vsize
+ {\large\bfseries L'extension\par \Huge \listofitems\par}
+ \bigbreak
+ v\loiver
+ \smallbreak
+ \longfrloidate
+ \vskip1.5cm
+ {Christian \bsc{Tellechea}\footnote{\texttt{unbonpetit@netc.fr}}\par Steven B. \bsc{Segletes}\footnote{steven.b.segletes.civ@mail.mil}}
+ \par
+ \endgroup
+ \vskip2cm
+ \leftskip=.2\linewidth \rightskip=.2\linewidth \small
+ Cette petite extension pour est destinée à lire une liste d'éléments dont le séparateur peut être choisi par l'utilisateur. Une fois la liste lue, ses éléments sont stockés dans une structure qui se comporte comme un tableau unidimensionnel et ainsi, il devient très facile d'accéder à un élément de la liste par son numéro. Par exemple, si la liste est stockée dans la macro \verb|\foo|, l'élément \no3 est désigné par \verb|\foo[3]|.
+
+ Un élément peut à son tour être une liste disposant d'un autre séparateur que celui de la liste de niveau supérieur, ce qui ouvre la voie à des imbrications et donne une syntaxe rappelant celle des tableaux à plusieurs dimensions du type \verb|\foo[3,2]| pour accéder à l'élément \no2 de la liste contenue dans l'élément \no3 de la liste de plus haut niveau.
+\end{titlepage}
+\def\listofitems{\textsf\loiname\xspace}
+\section{Avant-propos}
+\fbox{\vbox{\hsize\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax\textbf{Important} : à partir de la version 1.62, \listofitems nécessite un moteur \TeX{} fournissant la primitive \texttt{\string\expanded}. Si ce n'est pas le cas, un message d'erreur sera émis et la version 1.61 sera chargée (dernière version fonctionnant sans la primitive \texttt{\string\expanded}) : il est vivement conseillé de mettre à jour sa distribution \LaTeX{} afin de profiter d'un moteur \TeX{} récent permettant l'utilisation de cette nouvelle primitive.}}\medbreak
+
+Cette extension ne requiert aucun package, doit être utilisée avec un moteur \eTeX, et doit être appelée sous (pdf)(Xe)(lua)\LaTeX{} par
+\code|\usepackage{listofitems}|
+
+et sous (pdf)(Xe)(lua)\TeX{} par
+\code|\input listofitems.tex|
+
+\section{Lire une liste simple}
+\paragraph{Définir le séparateur}
+Le \verb|<séparateur>| par défaut est la virgule et si l'on souhaite en changer, il faut, avant de lire une liste d'éléments, le définir avec \verb|\setsepchar{<séparateur>}|. Un \verb|<séparateur>| est un ensemble de tokens dont les catcodes sont différents de 1 et 2 (les accolades ouvrantes et fermantes), 14 (habituellement \verb|%|) et 15. Le token de catcode 6 (habituellement \verb|#|) n'est accepté que s'il est suivi d'un entier auquel cas l'ensemble désigne l'argument d'une macro; en aucun cas ce token ne doit se trouver seul dans le \verb|<séparateur>|. Des commandes peuvent se trouver dans cet ensemble de tokens, y compris la primitive \verb|\par|.
+\smallbreak
+Le \verb|<séparateur>| \og\verb-/-\fg{} est réservé par défaut pour les listes imbriquées (voir page~\pageref{sep.listes.imbriquees}). Il ne faut donc pas écrire \og\verb-\setsepchar{/}-\fg{} car \listofitems comprendrait que l'on souhaite lire une liste imbriquée. Pour définir \og\verb-/-\fg comme \verb|<séparateur>| d'une liste simple, il faut, à l'aide de l'argument optionnel, choisir un autre \verb|<séparateur>| de listes imbriquées, par exemple \og\verb|.|\fg{} et écrire \og\verb+\setsepchar[.]{/}+\fg.
+\medbreak
+
+Il n'est pas possible de choisir \og\verb-|-\fg{} comme \verb|<séparateur>| car il entrerait en conflit avec l'opérateur logique \textbf{OU} noté \og\verb-||-\fg{} (voir plus bas). On peut cependant contourner cette limitation, à ses risques et périls, en écrivant \og\verb-\setsepchar{{|}}-\fg.
+
+\paragraph{Lire la liste}
+Pour lire la liste d'éléments, la commande \verb|\readlist<macroliste>{<liste>}| doit être appelée. Ce faisant, la \verb|<liste>| est lue et les éléments sont stockés dans une macro, notée \verb|<macroliste>| qui dès lors, se comporte comme un tableau composé des éléments de la \verb|<liste>|. Un élément est un ensemble de tokens dont les accolades \emph{doivent} être équilibrées. Les tokens de catcode 6 seuls, 14 et 15 ne sont pas autorisés dans les listes.
+
+Par exemple, pour définir la \verb|<macroliste>| nommée \verb|\foo|, on peut écrire
+\code|\setsepchar{,}
+\readlist\foo{12,abc, x y ,{\bfseries z}, ,\TeX,,!}|
+\setsepchar{,}
+\readlist\foo{12,abc, x y ,{\bfseries z}, ,\TeX,,!}
+
+Si la \verb|<liste>| est contenue dans une macro, alors cette macro est développée par \listofitems. On peut donc écrire \verb|\readlist<macroliste><macro>| ce qui donnerait
+
+\code|\setsepchar{,}
+\def\liste{12,abc, x y ,{\bfseries z}, ,\TeX,,!}
+\readlist\foo\liste|
+
+La macro \verb|\greadlist| agit comme \verb|\readlist| mais effectue des assignations \emph{globales} et par conséquent, la \verb|<macroliste>| est utilisable hors du groupe où a été exécutée \verb|\greadlist|.
+
+\paragraph{Accéder à un élément}
+La macro \verb|\foo| attend un argument numérique \emph{obligatoire} entre crochets, que nous notons $i$ et qui désigne le rang de l'élément auquel on souhaite accéder. Ainsi, \verb|\foo[1]| est\footnote{Il faut 2 développements à \texttt{\textbackslash foo[}$i$\texttt] pour obtenir l'élément \no$i$.} \og\verb|12|\fg. De la même façon, \verb|\foo[4]| est \og\verb|{\bfseries z}|\fg.
+
+Le nombre $i$ peut également être négatif auquel cas le comptage se fait à partir de la fin de la liste : $-1$ représente le dernier rang, $-2$ l'avant-dernier, etc. Si le nombre d'éléments est $n$, alors l'argument $-n$ est le premier élément.
+\medbreak
+
+D'une façon générale, si une \verb|<liste>| a une longueur $n$, alors l'index $i$ peut se trouver dans l'intervalle $[1\,;n]$ ou $[-n\,;-1]$ et dans le cas contraire, une erreur de compilation survient.
+
+Si l'index est vide, alors \verb|\foo[]| se développe en la \verb|<liste>| entière.
+
+\paragraph{Accéder à un séparateur}
+Lorsque \verb|\readlist\foo{<liste>}| est exécuté, la macro \verb|\foosep| est créé. Elle s'utilise avec la syntaxe \verb|\foosep[<index>]| et permet d'accéder au séparateur qui suit l'élément de rang \verb|<index>|. Le dernier séparateur (celui qui suit le dernier élément) est vide. Si l'\verb|<index>| est vide, \verb|\foosep[]| a un développement vide.
+
+\paragraph{Choisir plusieurs séparateurs possibles}
+Pour spécifier plusieurs séparateurs possibles, il faut utiliser l'opérateur \textbf{OU} noté \og\verb-||-\fg{}. On peut par exemple utiliser cette fonctionnalité pour isoler les termes dans une somme algébrique :
+
+\exemple/\setsepchar{+||-}
+\readlist\terme{17-8+4-11}
+1) \terme[1] (séparateur = \termesep[1])\par
+2) \terme[2] (séparateur = \termesep[2])\par
+3) \terme[3] (séparateur = \termesep[3])\par
+4) \terme[4] (séparateur = \termesep[4])/
+
+\paragraph{Nombre d'éléments}
+Si l'on écrit \verb|\readlist<macroliste>{<liste>}| alors la macro \verb|<macroliste>len| contient\footnote{C'est-à-dire qu'elle est purement développable et se développe en un nombre} le nombre d'éléments de la \verb|<liste>|. Dans l'exemple avec \verb|\foo|, la macro \verb|\foolen| contient \foolen.
+
+\paragraph{Afficher tous les éléments}
+À des fins de débogage, la macro \verb|\showitems<macroliste>| compose tous les éléments d'une liste tandis que que sa version étoilée affiche ces éléments \og détokénisés\footnote{La primitive \texttt{\string\detokenize} qui procède à cette dénaturation insère un espace après chaque séquence de contrôle.}\fg.
+
+\exemple/\showitems\foo\par
+\showitems*\foo/
+
+La présentation de chaque élément est confiée à la macro \verb|\showitemsmacro| dont le code est
+
+\code|\newcommand\showitemsmacro[1]{%
+ \begingroup\fboxsep=0.25pt \fboxrule=0.5pt \fbox{\strut#1}\endgroup
+ \hskip0.25em\relax}|
+
+Il est donc possible ---~et souhaitable~--- de la redéfinir si l'on cherche un autre effet.
+\medbreak
+
+La macro \verb|\fbox| et ses dimensions afférentes \verb|\fboxsep| et \verb|\fboxrule| sont définies par \listofitems lorsqu'on ne compile pas sous \LaTeX{} de façon à obtenir le même résultat qu'avec \LaTeX.
+
+\paragraph{Suppression des espaces extrêmes}
+Par défaut, \listofitems lit et prend en compte le (ou les) espaces se trouvant au début et à la fin d'un élément. Pour que ces espaces soient ignorés lors de la lecture de la \verb|<liste>|, il faut exécuter la version étoilée \verb|\readlist*<macro>{<liste>}|:
+
+\exemple|\setsepchar{,}
+\readlist*\foo{12,abc, x y ,{\bfseries z}, ,\TeX,,!}
+\showitems\foo|
+
+\paragraph{Gestion des éléments vides}
+Par défaut, \listofitems prend en compte les éléments vides. Ainsi, dans l'exemple précédent, le 2-développement de \verb|\foo[7]| est vide. Pour que des éléments vides (ceux délimités par deux séparateurs consécutifs dans la liste) soient ignorés, il faut, avant de lancer la macro \verb|\readlist|, exécuter la macro \verb|\ignoreemptyitems|. La macro \verb|\reademptyitems| revient au comportement par défaut.
+
+Cette option peut être utilisée seule ou combinée avec \verb|\readlist*| auquel cas la suppression des espaces extrêmes intervient \emph{avant} que \listofitems n'ignore les éléments vides :
+
+\exemple|\setsepchar{,}
+\ignoreemptyitems
+\readlist\foo{12,abc, x y ,{\bfseries z}, ,\TeX,,!}
+a) nombre d'éléments = \foolen\par
+ \showitems\foo
+
+\readlist*\foo{12,abc, x y ,{\bfseries z}, ,\TeX,,!}
+b) nombre d'éléments = \foolen\par
+ \showitems\foo|
+
+\paragraph{Itérer sur la liste}
+Une fois une liste lue par \verb|\readlist| et stockée dans une \verb|<macroliste>|, la commande \verb|\foreachitem <variable> \in <macroliste>{<code>}| itère sur la liste : la \verb|<variable>| est une macro choisire par l'utilisateur qui prendra tour à tour la valeur de chaque élément.
+
+La macro \verb|<variable>cnt| représente le numéro de l'élément contenu dans \verb|<variable>|.
+
+\exemple|\setsepchar{ }% séparateur = espace
+\readlist\phrase{Une phrase de test.}
+\foreachitem\mot\in\phrase{Le mot numéro \motcnt{} : \mot\par}|
+
+\paragraph{Assigner un élément à une macro}
+La commande \verb|\itemtomacro<macroliste>[index]<macro>| assigne à la \verb|<macro>| l'élément désigné par \verb|<macroliste>[index]|. La \verb|<macro>| ainsi définie est purement développable, sous réserve que l'élément qu'elle contient le soit.
+
+\exemple|\setsepchar{ }% séparateur = espace
+\readlist\phrase{Une phrase de test.}
+\itemtomacro\phrase[2]\unmot
+\meaning\unmot\par
+\itemtomacro\phrase[-1]\motdelafin
+\meaning\motdelafin|
+
+\section{Listes imbriquées}
+On parle de liste \og imbriquée\fg lorsque l'on demande à \listofitems de lire une liste où les éléments sont à leur tour compris comme une liste (dont le séparateur est différent de la liste de niveau supérieur). Le nombre d'imbrication n'est pas limité, mais dans la pratique, un niveau d'imbrication de 2, voire 3, semble un maximum.
+
+\paragraph{Définir les séparateurs}\label{sep.listes.imbriquees}
+Pour indiquer que les éléments de la liste doivent eux-mêmes être compris comme des listes et que la recherche des éléments sera récursive, il faut spécifier plusieurs \verb|<séparateurs>|, chacun correspondant à un niveau d'imbrication. Pour déclarer une \verb|<liste de séparateurs>| il faut définir le \verb|<séparateur>| de cette \verb|<liste de séparateurs>| à l'aide de l'argument optionnel de la macro \verb|\setsepchar| et écrire \verb|\setsepchar[<separateur>]{<liste des séparateurs>}|.
+
+Par défaut, le \verb|<séparateur>| est \og\verb-/-\fg. Ainsi, si l'on donne l'ordre
+
+\code|\setsepchar{\\/,/ }|
+
+on indique une profondeur récursive de 3 et on choisit comme séparateur de la \verb|<liste des séparateurs>| le caractère par défaut \og\verb-/-\fg{} :
+
+\begin{itemize}
+ \item les éléments de niveau 1 sont trouvés entre les séparateurs \og\verb|\\|\fg;
+ \item les éléments de niveau 2 sont trouvés dans les éléments de niveau 1 entre les séparateurs \og\verb|,|\fg{};
+ \item enfin, les éléments de niveau 3 sont trouvés dans ceux de niveau 2 entre les séparateurs \og\verb*| |\fg.
+\end{itemize}
+
+La \verb|<profondeur>| de recherche est contenue dans la macro purement développable \verb|\nestdepth|.
+
+\paragraph{Lire et accéder aux éléments}
+Pour les listes imbriquées, les index obéissent à la règle suivante :
+
+\begin{itemize}
+ \item \verb|[]| désigne la liste principale, c'est-à-dire l'argument de \verb|\readlist|;
+ \item \verb|[<i>]| désigne l'élément \no\verb|<i>| de la liste principale;
+ \item \verb|[<i>,<j>]| désigne l'élément \no\verb|<j>| de la liste constituée par l'élément évoqué au point précédent;
+ \item \verb|[<i>,<j>,<k>]| désigne l'élément \no\verb|<k>| de la liste constituée par l'élément évoqué au point précédent;
+ \item etc.
+\end{itemize}
+
+Comme pour les liste non imbriquées, les index peuvent être négatifs.
+
+Pour lire les éléments, la syntaxe de \verb|\readlist| est exactement la même qu'avec les listes simples :
+
+\exemple|\setsepchar{\\/,/ }
+\readlist\baz{1,2 a b,3 c\\4 d e f,5,6\\7,,8, ,9 xy z}
+a) \string\baz[1] est \baz[1]\par
+b) \string\baz[1,1] est \baz[1,1]\par
+c) \string\baz[1,1,1] est \baz[1,1,1]\par
+b) \string\bar[1,2] est \baz[1,2]\par
+e) \string\baz[1,2,3] est \baz[1,2,3]\par
+f) \string\baz[-2,1,-1] est \baz[-2,1,-1]|
+
+\paragraph{L'opérateur \og||\fg}
+Cet opérateur peut se trouver dans n'importe quel niveau d'imbrication.
+
+\exemple=\setsepchar[,]{+||-,*||/}
+\readlist\nombres{1+2*3-4/5*6}
+Terme 1 : \nombres[1]\par
+Terme 2 : \nombres[2] (facteurs : \nombres[2,1] et
+ \nombres[2,2])\par
+Terme 3 : \nombres[3] (facteurs : \nombres[3,1],
+ \nombres[3,2] et \nombres[3,3])=
+
+\paragraph{Nombre d'éléments}
+La macro \verb|\listlen<macrolist>[<index>]| nécessite 2 développements pour donner le nombre d'éléments de la liste spécifiée par l'\verb|<index>|.\medbreak
+
+La \verb|<profondeur>| de l'\verb|<index>| doit être strictement inférieure à celle de la \verb|<liste>|.\medbreak
+
+Dans le cas d'un \verb|<index>| vide, \verb|\listlen<macrolist>[]| donne en 2 développements le même résultat que \verb|<macrolist>len| qui le donne en 1.
+
+\exemple|\setsepchar{\\/,/ }
+\readlist\baz{1,2 a b,3 c\\4 d e f,5,6\\7,,8, ,9 xy z}
+a) \bazlen\ ou \listlen\baz[]\par
+b) \listlen\baz[1]\par
+c) \listlen\baz[2]\par
+d) \listlen\baz[3]\par
+e) \listlen\baz[3,1]\par
+f) \listlen\baz[3,4]\par% 2 éléments vides
+g) \listlen\baz[3,5]|
+
+\paragraph{Afficher les éléments}
+La macro \verb|\showitems<macrolist>[<index>]| affiche les éléments de la liste spécifiée par \verb|<index>|, selon le même principe que \verb|\listlen|.\medbreak
+
+La \verb|<profondeur>| de l'\verb|<index>| doit être strictement inférieure à celle de la \verb|<liste>|.
+
+\exemple|\setsepchar{\\/,/ }
+\readlist\baz{1,2 a b,3 c\\4 d e f,5,6\\7,,8, ,9 xy z}
+a) \showitems\baz[]\par
+b) \showitems\baz[1]\par
+c) \showitems\baz[2]\par
+d) \showitems\baz[3]\par
+e) \showitems\baz[3,1]\par
+f) \showitems\baz[3,4]\par% 2 éléments vides
+g) \showitems\baz[3,5]|
+
+\paragraph{Éléments vides et espaces extrêmes}
+La suppression des éléments vides et/ou des espaces extrêmes intervient dans \emph{tous} les éléments, quel que soit le degré d'imbrication. Il est clair que choisir un espace comme séparateur est inutile si l'on veut utiliser \verb|\readlist*|. C'est pourquoi dans cet exemple, \og\verb|*|\fg est choisi comme séparateur.
+
+Dans cet exemple, on ne supprime que les espaces extrêmes en gardant les éléments vides.
+
+\exemple|\setsepchar{\\/,/*}
+\readlist*\baz{1, 2*a*b ,3*c\\4*d*e*f,5,6\\7,,8, ,9* xy *z}
+a) \showitems\baz[]\par
+b) \showitems\baz[1]\par
+c) \showitems\baz[2]\par
+d) \showitems\baz[3]\par
+e) \showitems\baz[3,1]\par
+f) \showitems\baz[3,4]\par
+g) \showitems\baz[3,5]% "xy" sans espaces extrêmes|
+
+\paragraph{Itérer sur une liste}
+La syntaxe \verb|\foreachitem <variable> \in <macro>[<index>]{<code>}| reste valable où désormais, l'\verb|<index>| spécifie sur quel élément (compris comme une liste) on veut itérer.\medbreak
+
+La \verb|<profondeur>| de l'\verb|<index>| doit être strictement inférieure à celle de la \verb|<liste>|.
+
+\paragraph{Assigner un élément à une macro}
+La syntaxe \verb|\itemtomacro<macroliste>[<index>]<macro>| reste valable pour assigner à \verb|<macro>| l'élément spécifié par \verb|<macroliste>[<index>]|.
+
+\exemple[55]|\setsepchar[,]{\\, }
+\readlist\poeme{J'arrive tout couvert encore de rosée\\%
+Que le vent du matin vient glacer à mon front.\\%
+Souffrez que ma fatigue à vos pieds reposée\\%
+Rêve des chers instants qui la délasseront.}% 2e strophe de << Green >>, Paul Verlaine
+\itemtomacro\poeme[2]\vers
+2e vers = \vers
+
+\itemtomacro\poeme[2,-4]\mot
+Un mot = \mot|
+
+La macro \verb|\gitemtomacro| fait une assignation globale.
+
+\section{Tokens appariés}
+Pour le découpage des items, il est possible à partir de la version 1.6, de tenir compte de la présence de caractères \emph{appariés}. Ainsi, si une liste de caractères appariés est définie, chaque item s'étend jusqu'au prochain \verb|<séparateur>| qui équilibre les tokens appariés.
+
+Pour définir une liste de tokens appariés, on utilise
+
+\code|\defpair{<tok1><tok2><tok3><tok4>...}|
+
+où les tokens sont lus deux par deux pour former les paires d'appariement. Un \verb|<token>| d'appariement doit être constitué d'un seul caractère; les macros, primitives, espaces, accolades, token «\verb|#|», ensembles de plusieurs tokens entre accolades sont interdits. Deux tokens formant une paire \emph{doivent} être différents.
+
+\exemple/\setsepchar{+||-}
+\defpair{()[]}
+\readlist\termes{1+2*[3+4*(5+6-7)+8]-9+10}
+\showitems\termes/
+
+Pour revenir au comportement par défaut, c'est-à-dire sans tokens appariés, il faut exécuter
+
+\code|\defpair{}|
+
+Dans une expression, pour stocker dans une macro ce qui se trouve entre deux tokens appariés, on peut faire appel à
+
+\code|\insidepair<tok1><tok2>{<expression>}\macro|
+
+qui mettra dans la \verb|\macro| ce qui de trouve entre la paire \verb|<tok1><tok2>| dans l'\verb|<expression>|.
+
+\exemple/\setsepchar{+||-}
+\defpair{()}
+\readlist\termes{1+2*(3+4*(5+6-7)+8)-9+10}
+\showitems\termes
+
+\itemtomacro\termes[2]\parenterm
+Dans la parenthèse extérieure :
+\insidepair()\parenterm\inbigparen
+"\inbigparen"
+
+Dans la parenthèse intérieure :
+\insidepair()\inbigparen\insmallparen
+"\insmallparen"/
+
+\section{Le code}
+Toute suggestion, remontée de bug, remarque, demande, ajout ou modification de fonctionnalité est bienvenue; dans ce cas, j'invite les utilisateurs de \listofitems à m'envoyer un email à \verb|unbonpetit@netc.fr|.\medbreak
+
+Le code ci-dessous est l'exact verbatim du fichier \verb|listofitems.tex|. J'espère que les quelques commentaires qui le parsèment de-ci de-là seront suffisants pour que l'utilisateur ou le curieux comprenne la machinerie interne de ce package :
+
+\lstinputlisting[
+ language=TeX,
+ inputencoding=latin1,
+ moretexcs={unless,ifcsname,ifdefined,detokenize,numexpr,dimexpr,glueexpr,unexpanded,expanded},
+ basicstyle=\small\ttfamily\color{black!25},
+ identifierstyle=\bfseries\color{white},%
+ backgroundcolor=\color{black!85},
+ keywordstyle=\bfseries\color{orange},
+ commentstyle=\color{cyan!66},
+ columns=fixed,
+ alsoletter={\_},
+ tabsize=2,
+ extendedchars=true,
+ showspaces=false,
+ showstringspaces=false,
+ numbers=left,
+ numberstyle=\tiny\ttfamily\color{black},
+ breaklines=true,
+ prebreak={\hbox{$\rhookswarrow$}},
+ breakindent=3em,
+ breakautoindent=true,
+ xleftmargin=1em,
+ xrightmargin=0pt,
+ lineskip=0pt,
+ numbersep=1em,
+ classoffset=1,
+ alsoletter={\_},
+ morekeywords={defpair,insidepair,setsepchar,greadlist,readlist,listlen,foreachitem,%
+ showitems,showitemsmacro,itemtomacro,gitemtomacro,ignoreemptyitems,reademptyitems},
+ keywordstyle=\bfseries\color{red!85!black},
+ classoffset=0,
+ ]{listofitems.tex}
+\end{document} \ No newline at end of file
diff --git a/macros/generic/listofitems/listofitems.sty b/macros/generic/listofitems/listofitems.sty
new file mode 100644
index 0000000000..fb45d1dfab
--- /dev/null
+++ b/macros/generic/listofitems/listofitems.sty
@@ -0,0 +1,4 @@
+\expandafter\let\csname loi_fromsty\endcsname\relax
+\input listofitems.tex
+\ProvidesPackage\loiname[\loidate\space v\loiver\space Grab items in lists using user-specified sep char (CT)]
+\endinput \ No newline at end of file
diff --git a/macros/generic/listofitems/listofitems.tex b/macros/generic/listofitems/listofitems.tex
new file mode 100644
index 0000000000..6e2189f249
--- /dev/null
+++ b/macros/generic/listofitems/listofitems.tex
@@ -0,0 +1,606 @@
+% !TeX encoding = ISO-8859-1
+% Ce fichier contient le code de l'extension "listofitems"
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+\def\loiname {listofitems} %
+\def\loiver {1.63} %
+% %
+\def\loidate {2019/08/21} %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% Author : Christian Tellechea, Steven B. Segletes (contributor) %
+% Status : Maintained %
+% Maintainer : Christian Tellechea %
+% Email : unbonpetit@netc.fr %
+% steven.b.segletes.civ@mail.mil %
+% Package URL: https://www.ctan.org/pkg/listofitems %
+% Bug tracker: https://framagit.org/unbonpetit/listofitems/issues %
+% Repository : https://framagit.org/unbonpetit/listofitems/tree/master
+% Copyright : Christian Tellechea 2016-2019 %
+% Licence : Released under the LaTeX Project Public License v1.3c %
+% or later, see http://www.latex-project.org/lppl.txt %
+% Files : 1) listofitems.tex %
+% 2) listofitems.sty %
+% 3) listofitems-fr.tex %
+% 4) listofitems-fr.pdf %
+% 5) listofitems-en.tex %
+% 6) listofitems-en.pdf %
+% 7) README %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\expandafter\edef\csname loi_restorecatcode\endcsname{\catcode\number`\_=\number\catcode`\_\relax}
+\catcode`\_11
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%% gestion des erreurs + annonce package %%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\unless\ifdefined\loi_fromsty
+ \immediate\write -1 {Package: \loidate\space v\loiver\space Grab items in lists using user-specified sep char (CT)}%
+\fi
+
+\ifdefined\PackageError
+ \def\loi_error#1{\PackageError\loiname{#1}{Read the \loiname\space manual}}% pour LaTeX
+\else
+ \def\loi_error#1{\errmessage{Package \loiname\space Error: #1^^J}}% pour TeX
+\fi
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%% vérification des prérequis %%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\def\loi_checkprimitive#1#2#3{% Vérifie que #1 est une primitive et sinon, émet le message #2 et exécute #3
+ \begingroup
+ \edef\__tempa{\meaning#1}\edef\__tempb{\string#1}\expandafter
+ \endgroup
+ \ifx\__tempa\__tempb\else
+ \loi_error{#2}%
+ \def\loi_temp{#3}%
+ \loi_restorecatcode\expandafter\loi_temp
+ \fi
+}
+\loi_checkprimitive\eTeXversion
+ {You are not using an eTeX engine, listofitems cannot work.}
+ {\endinput}%
+\loi_checkprimitive\expanded
+ {the \string\expanded\space primitive is not provided by your TeX engine, listofitems v\loiver\space cannot work: loading listofitems v1.61}
+ {\input listofitemsold.tex\relax\endinput}%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%% macros auxiliaires %%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\def\loi_quark{\loi_quark}
+\long\def\loi_identity#1{#1}
+\long\def\loi_gobarg#1{}
+\long\def\loi_first#1#2{#1}
+\long\def\loi_second#1#2{#2}
+\long\def\loi_firsttonil#1#2\_nil{#1}
+\long\def\loi_antefi#1#2\fi{#2\fi#1}
+\long\def\loi_exparg#1#2{\expandafter\loi_exparg_a\expandafter{#2}{#1}}% \loi_exparg{<a>}{<b>} devient <a>{<*b>}
+\long\def\loi_exparg_a#1#2{#2{#1}}
+\long\def\loi_expafter#1#2{\expandafter\loi_expafter_a\expandafter{#2}{#1}}% \loi_expafter{<a>}{<b>} devient <a><*b>
+\long\def\loi_expafter_a#1#2{#2#1}
+\def\loi_macroname{\loi_ifinrange\escapechar[[0:255]]{\expandafter\loi_gobarg}{}\string}
+\def\loi_argcsname#1#{\loi_argcsname_a{#1}}
+\def\loi_argcsname_a#1#2{\loi_expafter{#1}{\csname#2\endcsname}}
+\long\def\loi_addtomacro#1#2{\loi_exparg{\def#1}{#1#2}}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%% macros de test %%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\long\def\loi_ifnum#1{\ifnum#1\expandafter\loi_first\else\expandafter\loi_second\fi}
+\long\def\loi_ifx#1{\ifx#1\expandafter\loi_first\else\expandafter\loi_second\fi}
+\long\def\loi_ifempty#1{\loi_exparg\loi_ifx{\expandafter\relax\detokenize{#1}\relax}}
+\def\loi_ifstar#1#2{\def\loi_ifstar_a{\loi_ifx{*\loi_nxttok}{\loi_first{#1}}{#2}}\futurelet\loi_nxttok\loi_ifstar_a}
+\edef\loi_escapechar{\expandafter\loi_gobarg\string\\}
+\long\def\loi_ifcsexpandable#1{% #1 est-il constitué d'une seule sc _développable_ ?
+ \loi_ifempty{#1}
+ {\loi_second
+ }
+ {\loi_ifspacefirst{#1}
+ {\loi_second% si espace en 1er, faux
+ }
+ {\csname loi_\if\loi_escapechar\expandafter\loi_firsttonil\detokenize{#1}\_nil first\else second\fi\endcsname
+ {\loi_exparg\loi_ifempty{\loi_gobarg#1}% 1 seul arg commençant par "\" ?
+ {\def\loi_tempa{#1}\loi_exparg{\def\loi_tempb}{#1}% est-il développable ?
+ \expandafter\unless\loi_ifx{\loi_tempa\loi_tempb}%
+ }
+ {\loi_second
+ }%
+ }
+ {\loi_second
+ }%
+ }%
+ }%
+}
+\def\loi_ifinrange#1[[#2:#3]]{\expandafter\unless\loi_ifnum{\numexpr(#1-#2)*(#1-#3)>0 }}
+\def\loi_ifstring#1#2{% si la chaine #1 est contenue dans #2
+ \def\loi_ifstring_a##1#1##2\_nil{\loi_ifempty{##2}\loi_second\loi_first}%
+ \loi_ifstring_a#2#1\_nil% appel de la macro auxiliaire
+}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%% macro \loi_foreach %%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\newcount\loi_cnt_foreach_nest \loi_cnt_foreach_nest=0
+\def\end_foreach{\end_foreach}
+\def\loi_def_foreachsep#1{%
+ \long\def\loi_foreach##1\in##2##3{%
+ \global\advance\loi_cnt_foreach_nest1
+ \loi_argcsname\def{loop_code_\number\loi_cnt_foreach_nest}{##3}%
+ \loi_foreach_a##1##2#1\end_foreach#1%
+ \loi_argcsname\let{loop_code_\number\loi_cnt_foreach_nest}\empty
+ \global\advance\loi_cnt_foreach_nest-1
+ }%
+ \long\def\loi_foreach_a##1##2#1{%
+ \def##1{##2}%
+ \loi_ifx{\end_foreach##1}
+ {}
+ {\csname loop_code_\number\loi_cnt_foreach_nest\endcsname% exécute le code
+ \loi_foreach_a##1%
+ }%
+ }%
+}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%% macros gérant l'appariement %%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\long\def\defpair#1{%
+ \let\loi_listofpair\empty
+ \loi_ifempty{#1}
+ {}
+ {\defpair_a{}#1\loi_quark\loi_quark}%
+}
+\long\def\defpair_a#1#2#3{%
+ \loi_ifx{\loi_quark#2}
+ {\def\loi_sanitizelist##1,\_nil{\def\loi_listofpair{##1}}%
+ \loi_sanitizelist#1\_nil
+ }
+ {\loi_if_validpair#2#3%
+ {\long\def\loi_paired_a{#2}\long\def\loi_paired_b{#3}%
+ \loi_ifx{\loi_paired_a\loi_paired_b}
+ {\loi_error{Paired tokens must not be equal, the pair \detokenize{#2#3} is ignored}%
+ \defpair_a{#1}%
+ }
+ {\defpair_a{#1#2#3,}%
+ }%
+ }
+ {\loi_error{Invalid paired tokens, the pair "\detokenize{#2}" and "\detokenize{#3}" is ignored}%
+ \defpair_a{#1}%
+ }%
+ }%
+}
+\long\def\loi_if_validpair#1#2{%
+ \def\loi_validpair{1}%
+ \loi_if_invalid_pairtoken{#1}{\def\loi_validpair{0}}%
+ \loi_if_invalid_pairtoken{#2}{\def\loi_validpair{0}}%
+ \loi_ifnum{\loi_validpair=1 }
+}
+\long\def\loi_if_invalid_pairtoken#1{%
+ \loi_ifempty{#1}
+ {\loi_identity
+ }
+ {\loi_ifspacefirst{#1}
+ {\loi_identity
+ }
+ {\loi_exparg\loi_ifempty{\loi_gobarg#1}% 1 seul token ?
+ {\ifcat\relax\noexpand#1\expandafter\loi_identity\else\expandafter\loi_gobarg\fi}
+ {\loi_identity}% si plusieurs tokens, faux
+ }%
+ }%
+}
+\long\def\loi_count_occur#1\in#2:#3{% compte le nombre d'occurrences de #1 dans #2 et met le résultat dans la macro #3
+ \long\def\loi_count_occur_a##1##2#1##3\_nil{%
+ \loi_ifempty{##3}
+ {\def#3{##1}}
+ {\expandafter\loi_count_occur_a\number\numexpr##1+1\relax##3\_nil}%
+ }%
+ \loi_count_occur_a0#2#1\_nil
+}
+\long\def\loi_check_pair#1#2\in#3{% teste l'appariement de #1 et #2 dans #3
+ \loi_ifempty{#3}
+ {\loi_second
+ }
+ {\loi_count_occur#1\in#3:\loi_tempa
+ \loi_count_occur#2\in#3:\loi_tempb
+ \loi_ifnum{\loi_tempa=\loi_tempb\relax}%
+ }%
+}
+\long\def\loi_grabpaired_expr#1#2#3#4#5{% #1=liste de paires #2=expression #3=séparateur #4=résultat #5=ce qui reste
+ \let#4\empty
+ \def\loi_remain{#2#3}%
+ \loi_foreach\loi_pair\in{#1}{\expandafter\loi_grabpaired_expr_a\loi_pair{#3}#4}%
+ \def\loi_remove_lastsep##1#3\_nil{\def#4{##1}}%
+ \expandafter\loi_remove_lastsep#4\_nil
+ \loi_expafter{\long\def\loi_grab_remain}#4##1\_nil{%
+ \loi_ifempty{##1}
+ {\let#5\empty}
+ {\loi_exparg{\def#5}{\loi_gobarg##1}}%
+ }%
+ \loi_grab_remain#2\_nil
+}
+\long\def\loi_grabpaired_expr_a#1#2#3#4{% #1#2=paire en cours #3=séparateur #4=résultat
+ \loi_exparg{\loi_check_pair#1#2\in}#4% si les paires sont appariées dans le résultat
+ {}% passer à la paire suivante
+ {\long\def\loi_grabpaired_expr_b##1#3##2\_nil{%
+ \loi_addtomacro#4{##1#3}% ajouter au résultat ce qui est jusqu'au prochain séparateur
+ \def\loi_remain{##2}%
+ \loi_exparg{\loi_check_pair#1#2\in}{#4}
+ {}
+ {\loi_ifempty{##2}
+ {\loi_error{"\detokenize{#1}" and "\detokenize{#2}" are not paired}}
+ {\loi_grabpaired_expr_b##2\_nil}%
+ }%
+ }%
+ \expandafter\loi_grabpaired_expr_b\loi_remain\_nil
+ }%
+}
+\def\insidepair#1#2#3#4{% #1#2=paire #3=expr #4=macro reçevant le resultat
+ \loi_if_validpair#1#2%
+ {\loi_ifcsexpandable{#3}
+ {\loi_exparg{\insidepair#1#2}{#3}#4%
+ }
+ {\loi_check_pair#1#2\in{#3}% si les paires sont appariées dans le résultat
+ {\def\insidepair_a##1#1##2\_nil{\insidepair_b##2\_nil{#1}}%
+ \def\insidepair_b##1#2##2\_nil##3{%
+ \loi_check_pair#1#2\in{##3##1#2}
+ {\loi_exparg{\def#4}{\loi_gobarg##3##1}%
+ \def\loi_remainafterparen{##2}%
+ }%
+ {\insidepair_b##2\_nil{##3##1#2}%
+ }%
+ }%
+ \insidepair_a#3\_nil
+ }
+ {\loi_error{"\detokenize{#1}" and "\detokenize{#2}" are not paired in "#3"}%
+ }%
+ }%
+ }
+ {\loi_error{Invalid paired tokens "\detokenize{#1}" and "\detokenize{#2}", empty \string#4 returned}% et bim
+ \let#4\empty% voilà, bien fait pour vos gueules
+ }%
+}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%% macro \loi_fornum %%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\def\loi_fornum#1=#2to#3\do{%
+ \edef#1{\number\numexpr#2}%
+ \expandafter\loi_fornum_a
+ \csname loi_fornum_\string#1\expandafter\endcsname\expandafter
+ {\number\numexpr#3\expandafter}%
+ \expanded{\ifnum#1<\numexpr#3\relax>+\else<-\fi}%
+ #1%
+}
+\long\def\loi_fornum_a#1#2#3#4#5#6{%
+ \def#1{%
+ \unless\ifnum#5#3#2\relax
+ \loi_antefi{#6\edef#5{\number\numexpr#5#41\relax}#1}%
+ \fi}%
+ #1%
+}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%% macro retirant les espaces extrêmes %%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\long\def\loi_ifspacefirst#1{\expandafter\loi_ifspacefirst_a\detokenize{#10} \_nil}
+\long\def\loi_ifspacefirst_a#1 #2\_nil{\loi_ifempty{#1}}
+\loi_expafter{\def\loi_gobspace}\space{}
+\long\def\loi_removefirstspaces#1{\loi_ifspacefirst{#1}{\loi_exparg\loi_removefirstspaces{\loi_gobspace#1}}{\unexpanded{#1}}}%##BUGFIX v1.63
+\begingroup
+ \catcode0 12
+ \long\gdef\loi_removelastspaces#1{\loi_removelastspaces_a#1^^00 ^^00\_nil}
+ \long\gdef\loi_removelastspaces_a#1 ^^00{\loi_removelastspaces_b#1^^00}
+ \long\gdef\loi_removelastspaces_b#1^^00#2\_nil{\loi_ifspacefirst{#2}{\loi_removelastspaces_a#1^^00 ^^00\_nil}{\unexpanded{#1}}}
+\endgroup
+\long\def\loi_removeextremespaces#1{\expanded{\loi_exparg\loi_removelastspaces{\expanded{\loi_removefirstspaces{#1}}}}}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%% macro publique \setsepchar %%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\def\setsepchar{\futurelet\loi_nxttok\setsepchar_a}
+\def\setsepchar_a{\loi_ifx{[\loi_nxttok}\setsepchar_b{\setsepchar_b[/]}}
+\long\def\setsepchar_b[#1]#2{% #1=sepcar de <liste des sepcar> #2=<liste des sepcar>
+ \loi_ifempty{#1}
+ {\loi_error{Empty separator not allowed, separator "/" used}%
+ \setsepchar_b[/]{#2}%
+ }
+ {\def\loi_currentsep{#1}%
+ \_removeextremespacesfalse
+ \loi_nestcnt1 % réinitaliser niveau initial à 1
+ \def\nestdepth{1}%
+ \loi_argcsname\let{loi_previndex[\number\loi_nestcnt]}\empty
+ \def\loi_listname{loi_listofsep}%
+ \let\loi_def\def \let\loi_edef\edef \let\loi_let\let
+ \let\loi_listofpair_saved\loi_list_ofpair
+ \let\loi_list_ofpair\empty
+ \loi_ifempty{#2}
+ {\loi_error{Empty list of separators not allowed, "," used}%
+ \readlist_g1{,}%
+ }
+ {\readlist_g1{#2}%
+ }%
+ \loi_argcsname\let\nestdepth{loi_listofseplen[0]}%
+ \loi_argcsname\let\loi_currentsep{loi_listofsep[1]}% 1er car de séparation
+ \let\loi_listofpair\loi_listofpair_saved
+ }%
+}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%% macro normalisant l'index %%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\def\loi_normalizeindex#1#2{% #1=macroname #2=liste d'index --> renvoie {err}{indx norm}
+ \loi_ifempty{#2}
+ {{}{}}
+ {\loi_exparg{\loi_normalizeindex_a1{}}{\number\csname#1nest\endcsname}{#1}#2,\loi_quark,}%
+}%
+\def\loi_normalizeindex_a#1#2#3#4#5,{% #1=compteur de profondeur #2=index précédents #3=profondeur max #4=macroname #5=index courant
+ \loi_ifx{\loi_quark#5}
+ {\loi_normalizeindex_c#2\loi_quark% supprimer la dernière virgule
+ }
+ {\loi_ifnum{#1>#3 }
+ {\loi_invalidindex{Too deeply nested index, index [.] retained}{#2}% si profondeur trop grande
+ }
+ {\loi_ifinrange\ifnum\numexpr#5<0 -1*\fi(#5)[[1:\csname #4len[#20]\endcsname]]% si abs(#5) hors de [1,len]
+ {\loi_exparg\loi_normalizeindex_b{\number\numexpr#5\ifnum\numexpr#5<0 +\csname #4len[#20]\endcsname+1\fi}{#1}{#2}{#3}{#4}}
+ {\loi_invalidindex{#5 is an invalid index, index [.] retained}{#2}}%
+ }%
+ }%
+}
+\def\loi_normalizeindex_b#1#2#3{\loi_exparg\loi_normalizeindex_a{\number\numexpr#2+1}{#3#1,}}% #1=index à rajouter #2=compteur de profondeur #3=index précédents
+\def\loi_normalizeindex_c#1,\loi_quark{{}{#1}}
+\def\loi_invalidindex#1#2{\loi_ifempty{#2}{\loi_invalidindex_a{#1},}\loi_invalidindex_a{#1}{#2}}
+\def\loi_invalidindex_a#1#2{\loi_invalidindex_b#1\loi_quark#2\loi_quark}
+\def\loi_invalidindex_b#1[.]#2\loi_quark#3,\loi_quark#4\loi_quark,{{#1[#3]#2}{#3}}% #4= index ignorés
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%% macro publique \readlist %%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\newcount\loi_nestcnt
+\def\greadlist{\let\loi_def\gdef\let\loi_edef\xdef\def\loi_let{\global\let}\readlist_a}%
+\def\readlist{\let\loi_def\def\let\loi_edef\edef\let\loi_let\let\readlist_a}
+\def\readlist_a{%
+ \loi_nestcnt1 % niveau initial = 1
+ \loi_argcsname\let{loi_previndex[\number\loi_nestcnt]}\empty
+ \loi_ifstar{\_removeextremespacestrue\readlist_b}{\_removeextremespacesfalse\readlist_b}%
+}
+\long\def\readlist_b#1#2{% #1=macro stockant les éléments #2=liste des éléments
+ \loi_ifcsexpandable{#2}
+ {\loi_exparg{\readlist_b#1}{#2}%
+ }
+ {\loi_edef\loi_listname{\loi_macroname#1}%
+ \loi_exparg{\readlist_c#1{#2}}{\loi_listname}%%
+ }%
+}
+\long\def\readlist_c#1#2#3{% #1=macro stockant les éléments #2=liste des éléments #3=macroname
+ \loi_argcsname\loi_let{#3nest}\nestdepth
+ \loi_argcsname\loi_def{#3[]}{#2}% la liste entière
+ \loi_argcsname\loi_def{#3sep[]}{}% séparateur vide
+ \loi_ifempty{#2}
+ {\loi_def#1[##1]{}%
+ \loi_argcsname\loi_def{#3len}{0}\loi_argcsname\loi_def{#3len[0]}{0}%
+ \loi_error{Empty list ignored, nothing to do}%
+ }
+ {\loi_def#1[##1]{\expanded{\expandafter\readlist_d\expanded{\loi_normalizeindex{#3}{##1}}{#3}}}%
+ \loi_argcsname\loi_def{#3sep}[##1]{\expanded{\expandafter\readlist_d\expanded{\loi_normalizeindex{#3}{##1}}{#3sep}}}%
+ \readlist_e{#2}%
+ \loi_argcsname\loi_argcsname\loi_let{#3len}{#3len[0]}% longueur du niveau 0
+ }%
+}
+\def\readlist_d#1#2#3{%
+ \unexpanded\expandafter\expandafter\expandafter{\csname#3[#2]\expandafter\endcsname\expandafter}%
+ \expanded{\loi_ifempty{#1}{}{\unexpanded{\unexpanded{\loi_error{#1}}}}}%
+}
+\def\readlist_e{%
+ \loi_argcsname\loi_let\loi_currentsep{loi_listofsep[\number\loi_nestcnt]}%
+ \expandafter\readlist_f\loi_currentsep||\_nil
+}
+\long\def\readlist_f#1||#2\_nil#3{\readlist_g1{#3#1}}% #1=<sep courant simple> #3=liste -> rajoute un élément vide pour le test \ifempty ci dessous
+\long\def\readlist_g#1#2{% #1=compteur d'index #2=liste d'éléments à examiner terminée par <sep courant simple> >>RIEN laissé après
+ \loi_ifempty{#2}
+ {\loi_argcsname\loi_edef{\loi_listname len[\csname loi_previndex[\number\loi_nestcnt]\endcsname0]}{\number\numexpr#1-1\relax}%
+ \loi_argcsname\loi_let{\loi_listname sep[\csname loi_previndex[\number\loi_nestcnt]\endcsname\number\numexpr#1-1\relax]}\empty% le dernier <sep> est <vide> ##NEW v1.52
+ \advance\loi_nestcnt-1
+ \loi_argcsname\loi_let\loi_currentsep{loi_listofsep[\number\loi_nestcnt]}%
+ }
+ {\loi_expafter{\readlist_h{#2}{}}\loi_currentsep||\loi_quark||#2\_nil{#1}% aller isoler le 1er item
+ }%
+}
+\long\def\readlist_h#1#2#3||{% #1=liste restante #2=<dernier sep utilisé> #3=<sep courant>
+ \loi_ifx{\loi_quark#3}% on a épuisé tous les <séparateurs> ? RESTE à lire <expr+sep1>\_nil{<compteur>}
+ {\loi_ifempty{#2}% si #2 vide, aucun <sep utilisé> n'a été trouvé, il reste à lire "<liste complète>\_nil"
+ {\long\def\readlist_i##1\_nil##2{\loi_exparg{\readlist_j{##2}{}}{\loi_gobarg##1}{#2}}% ##2=compteur d'index
+ }
+ {\loi_ifx{\loi_listofpair\empty}% paires définies ?
+ {\long\def\readlist_i##1#2##2\_nil##3{\loi_exparg{\readlist_j{##3}{##2}}{\loi_gobarg##1}{#2}}%
+ }
+ {\long\def\readlist_i##1\_nil##2{%
+ \loi_exparg{\loi_exparg\loi_grabpaired_expr\loi_listofpair}{\loi_gobarg##1}{#2}\loi_grabpaired_result\loi_grabpaired_remain
+ \loi_exparg{\loi_exparg{\readlist_j{##2}}{\loi_grabpaired_remain}}{\loi_grabpaired_result}{#2}}%{#}
+ }%
+ }%
+ \readlist_i\relax% le \relax meuble l'argument délimité
+ }
+ {\long\def\readlist_i##1#3##2\_nil{%
+ \loi_ifempty{##2}% si <liste restante> ne contient pas le <sep courant>
+ {\readlist_h{#1}{#2}% recommencer avec le même <sep utile>
+ }%
+ {\loi_ifx{\loi_listofpair\empty}% si pas de paires définies
+ {\loi_exparg\readlist_h{\loi_gobarg##1#3}{#3}% raccourcir <liste restante> et <sep courant>:=<sep utile>% ##BUGFIX v1.53
+ }%
+ {\loi_exparg\loi_grabpaired_expr\loi_listofpair{#1#3}{#3}\loi_grabpaired_result\loi_grabpaired_remain
+ \loi_ifx{\loi_grabpaired_remain\empty}% si liste non raccourcie #BUGFIX 1.63
+ {\loi_exparg\readlist_h{\loi_grabpaired_result}{#2}}% garder le précédent <sep>
+ {\loi_exparg\readlist_h{\loi_grabpaired_result}{#3}}%
+ }%
+ }%
+ }%
+ \readlist_i\relax#1#3\_nil% ##BUGFIX v1.53
+ }%
+}
+\long\def\readlist_j#1#2#3{% #1=compteur d'index #2=liste restante #3=élément courant
+ \loi_ifnum{0\loi_exparg\loi_ifspacefirst{\loi_currentsep}{}1\if_removeextremespaces1\fi=11 }% s'il faur retirer les espaces extrêmes
+ {\loi_exparg{\loi_exparg{\readlist_k{#1}{#2}}}{\loi_removeextremespaces{#3}}}% redéfinir l'élément courant
+ {\readlist_k{#1}{#2}{#3}}%
+}
+\long\def\readlist_k#1#2#3#4{% #1=compteur d'index #2=liste restante #3=élément courant #4=sep utilisé
+ \loi_ifnum{0\if_ignoreemptyitems1\fi\loi_ifempty{#3}1{}=11 }
+ {\readlist_g{#1}{#2}% si l'on n'ignore pas les éléments vides
+ }%
+ {\loi_argcsname\loi_def{\loi_listname[\csname loi_previndex[\number\loi_nestcnt]\endcsname#1]}{#3}% assignation
+ \loi_argcsname\loi_def{\loi_listname sep[\csname loi_previndex[\number\loi_nestcnt]\endcsname#1]}{#4}% assignation du <sep> actuel à la macro \<macrolist>sep
+ \loi_ifnum{\loi_nestcnt<\nestdepth\relax}% si imbrication max non atteinte
+ {\advance\loi_nestcnt1
+ \loi_argcsname\edef{loi_previndex[\number\loi_nestcnt]}{\csname loi_previndex[\number\numexpr\loi_nestcnt-1]\endcsname#1,}%
+ \readlist_e{#3}% recommencer avec l'élément courant
+ }
+ {}%
+ \loi_exparg\readlist_g{\number\numexpr#1+1}{#2}% puis chercher l'élément suivant dans la liste restante
+ }%
+}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%% macro \listlen %%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\def\listlen#1[#2]{%
+ \expanded{%
+ \loi_ifempty{#2}
+ {\csname\loi_macroname#1len[0]\endcsname}
+ {\loi_exparg\listlen_a{\expanded{\loi_macroname#1}}{#2}}%
+ }%
+}
+\def\listlen_a#1#2{% #1=macro name #2=index non normalisé prendre <profondeur max-1>
+ \expandafter\listlen_b\expanded{\loi_normalizeindex{#1}{#2}}{#1}%
+}
+\def\listlen_b#1#2#3{% #1=err #2=index normalisé #3=macroname
+ \csname#3len[#2,0]\expandafter\endcsname
+ \expanded{\loi_ifempty{#1}{}{\unexpanded{\unexpanded{\loi_error{#1}}}}}%
+}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%% macro \foreachitem %%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\def\foreachitem#1\in#2{%
+ \edef\foreachitem_a{\noexpand\foreachitem_c\noexpand#1{\expandafter\noexpand\csname\loi_macroname#1cnt\endcsname}{\loi_macroname#2}}%
+ \futurelet\loi_nxttok\foreachitem_b
+}
+\def\foreachitem_b{\loi_ifx{\loi_nxttok[}\foreachitem_a{\foreachitem_a[]}}
+\def\foreachitem_c#1#2#3[#4]{% prendre <profondeur max-1>
+ \expandafter\foreachitem_d\expanded{\loi_normalizeindex{#3}{#4}}#1{#2}{#3}%
+}
+\def\foreachitem_d#1#2{\loi_ifempty{#2}{\foreachitem_e{#1}{}}{\foreachitem_e{#1}{#2,}}}% #1=err #2=index norm
+\long\def\foreachitem_e#1#2#3#4#5#6{% #1=err #2=index norm #3=macroiter #4=compteur associé #5=nom de macrolist #6=code
+ \loi_ifnum{\csname#5len[#20]\endcsname>0 }
+ {\loi_ifempty{#1}{}{\loi_error{#1}}%
+ \loi_fornum#4=1to\csname#5len[#20]\endcsname\do{\loi_argcsname\let#3{#5[#2#4]}#6}%
+ }
+ {}%
+}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%% macro \showitem %%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\def\showitems{\loi_ifstar{\let\showitems_cmd\detokenize\showitems_a}{\let\showitems_cmd\loi_identity\showitems_a}}
+\def\showitems_a#1{\def\showitems_b{\showitems_d#1}\futurelet\loi_nxttok\showitems_c}
+\def\showitems_c{\loi_ifx{\loi_nxttok[}\showitems_b{\showitems_b[]}}
+\def\showitems_d#1[#2]{\foreachitem\showitems_iter\in#1[#2]{\showitemsmacro{\expandafter\showitems_cmd\expandafter{\showitems_iter}}}}
+\unless\ifdefined\fbox
+ \newdimen\fboxrule \newdimen\fboxsep \fboxrule=.4pt \fboxsep=3pt % réglages identiques à LaTeX
+ \def\fbox#1{% imitation de la macro \fbox de LaTeX, voir pages 271 à 274 de "Apprendre à programmer en TeX"
+ \hbox{%
+ \vrule width\fboxrule
+ \vtop{%
+ \vbox{\hrule height\fboxrule \kern\fboxsep \hbox{\kern\fboxsep#1\kern\fboxsep}}%
+ \kern\fboxsep \hrule height\fboxrule
+ }\vrule width\fboxrule
+ }%
+ }
+\fi
+\def\showitemsmacro#1{% encadrement par défaut
+ \begingroup\fboxsep=0.25pt \fboxrule=0.5pt \fbox{\strut#1}\endgroup
+ \hskip0.25em\relax
+}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%% macro \itemtomacro %%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\def\itemtomacro#1[#2]{% #1[#2]=item non encore lu: #3=macro
+ \edef\loi_listname{\loi_macroname#1}%
+ \expandafter\itemtomacro_a\expanded{\loi_normalizeindex{\loi_listname}{#2}}\let
+}
+\def\gitemtomacro#1[#2]{% #1[#2]=item
+ \xdef\loi_listname{\loi_macroname#1}%
+ \expandafter\itemtomacro_a\expanded{\loi_normalizeindex{\loi_listname}{#2}}{\global\let}%
+}
+\def\itemtomacro_a#1#2#3#4{%
+ \loi_ifempty{#1}{}{\loi_error{#1}}%
+ \loi_argcsname#3#4{\loi_listname[#2]}%
+}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%% réglages par défaut %%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\newif\if_removeextremespaces
+\newif\if_ignoreemptyitems
+\let\ignoreemptyitems\_ignoreemptyitemstrue
+\let\reademptyitems\_ignoreemptyitemsfalse
+\loi_def_foreachsep{,}
+\loi_restorecatcode
+\reademptyitems
+\setsepchar{,}
+\defpair{}
+\endinput
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%% historique %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+v1.0 19/8/2016
+ - Première version publique
+----------------------------------------------------------------------
+v1.1 01/09/2016
+ - Stockage des séparateurs dans <macrolist>sep
+ - bug corrigé dans \loi_restorecatcode
+----------------------------------------------------------------------
+v1.2 22/10/2016
+ - macros \greadlist et \gitemtomacro pour la globalité
+----------------------------------------------------------------------
+v1.3 18/11/2016
+ - bugs corrigés dans la gestion de la globalité
+----------------------------------------------------------------------
+v1.4 05/10/2017
+ - test \loi_ifprimitive ajouté au test \loi_ifcs
+ - suppression de \loi_expafternil, création de \loi_expafter,
+ modification de \loi_argcsname
+ - correction d'un bug : \setsepchar{\par} ne provoque plus d'erreur.
+ \loi_ifnum devient \long
+----------------------------------------------------------------------
+v1.5 06/10/2017
+ - correction d'un bug dans \loi_ifcs
+----------------------------------------------------------------------
+v1.51 24/10/2017
+ - correction d'un bug dans \loi_ifcs
+----------------------------------------------------------------------
+v1.52 13/01/2018
+ - le dernier séparateur est <vide>
+----------------------------------------------------------------------
+v1.53 13/03/2018
+ - correction d'un bug dans \readlist_i
+----------------------------------------------------------------------
+v1.6 01/11/2018
+ - possibilité d'appariement de tokens dans les items
+----------------------------------------------------------------------
+v1.61 03/03/2019
+ - la macro \loi_ifcs contient une erreur de conception. Il faut
+ tester si le token est un sc && s'il est développable pour
+ renvoyer vrai car il existe des sc non développables && qui ne
+ sont _pas_ des primitives.
+ Macro rebaptisée \loi_ifcsexpandable
+----------------------------------------------------------------------
+v1.62 18/05/2019
+ - utilisation de la nouvelle primitive \expanded au lieu du
+ désormais obsolète \romannumeral
+ - bug corrigé dans \loi_ifcsexpandable
+----------------------------------------------------------------------
+v1.63 21/08/2019
+ - bug corrigé dans \readlist_h avec les tokens appariés
+ - bug corrigé \loi_removefirstspaces est désormais \long \ No newline at end of file
diff --git a/macros/generic/listofitems/listofitemsold.tex b/macros/generic/listofitems/listofitemsold.tex
new file mode 100644
index 0000000000..644200a6f0
--- /dev/null
+++ b/macros/generic/listofitems/listofitemsold.tex
@@ -0,0 +1,572 @@
+% !TeX encoding = ISO-8859-1
+% Ce fichier contient le code de l'extension "listofitems"
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+\def\loiname {listofitems} %
+\def\loiver {1.61} %
+% %
+\def\loidate {2019/03/03} %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% Author : Christian Tellechea, Steven B. Segletes %
+% Status : Maintained %
+% Maintainer : Christian Tellechea %
+% Email : unbonpetit@netc.fr %
+% steven.b.segletes.civ@mail.mil %
+% Package URL: https://www.ctan.org/pkg/listofitems %
+% Bug tracker: https://framagit.org/unbonpetit/listofitems/issues %
+% Repository : https://framagit.org/unbonpetit/listofitems/tree/master
+% Copyright : Christian Tellechea 2016-2019 %
+% Licence : Released under the LaTeX Project Public License v1.3c %
+% or later, see http://www.latex-project.org/lppl.txt %
+% Files : 1) listofitems.tex %
+% 2) listofitems.sty %
+% 3) listofitems-fr.tex %
+% 4) listofitems-fr.pdf %
+% 5) listofitems-en.tex %
+% 6) listofitems-en.pdf %
+% 7) README %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\ifdefined\ProvidesPackage\else
+ \immediate\write -1 {%
+ Package: \loidate\space v\loiver\space Grab items in lists using user-specified sep char (CT)}%
+\fi
+
+\expandafter\edef\csname loi_restorecatcode\endcsname{\catcode\number`\_=\number\catcode`\_\relax}
+\catcode`\_11
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%% gestion des erreurs %%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\ifdefined\PackageError
+ \def\loi_error#1{\PackageError\loiname{#1}{Read the manual}}% pour LaTeX
+\else
+ \def\loi_error#1{\errmessage{Package \loiname\space Error: #1^^J}}% pour TeX
+\fi
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%% vérification de la présence de etex %%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\begingroup
+\edef\__tempa{\meaning\eTeXversion}\edef\__tempb{\string\eTeXversion}%
+\ifx\__tempa\__tempb
+ \endgroup
+\else
+ \endgroup
+ \loi_error{You are not using an eTeX engine, listofitems cannot work.}%
+ \loi_restorecatcode\expandafter\endinput
+\fi
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%% macros auxiliaires %%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\chardef\loi_stop=0
+\def\loi_quark{\loi_quark}
+\long\def\loi_identity#1{#1}
+\long\def\loi_gobarg#1{}
+\long\def\loi_first#1#2{#1}
+\long\def\loi_second#1#2{#2}
+\long\def\loi_firsttonil#1#2\_nil{#1}
+\long\def\loi_antefi#1#2\fi{#2\fi#1}
+\long\def\loi_exparg#1#2{\expandafter\loi_exparg_a\expandafter{#2}{#1}}% \loi_exparg{<a>}{<b>} devient <a>{<*b>}
+\long\def\loi_exparg_a#1#2{#2{#1}}
+\long\def\loi_expafter#1#2{\expandafter\loi_expafter_a\expandafter{#2}{#1}}% \loi_expafter{<a>}{<b>} devient <a><*b>
+\long\def\loi_expafter_a#1#2{#2#1}
+\def\loi_macroname{\loi_ifinrange\escapechar[[0:255]]{\expandafter\loi_gobarg}{}\string}
+\def\loi_argcsname#1#{\loi_argcsname_a{#1}}
+\def\loi_argcsname_a#1#2{\loi_expafter{#1}{\csname#2\endcsname}}
+\long\def\loi_addtomacro#1#2{\loi_exparg{\def#1}{#1#2}}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%% macros de test %%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\long\def\loi_ifnum#1{\ifnum#1\expandafter\loi_first\else\expandafter\loi_second\fi}
+\long\def\loi_ifx#1{\ifx#1\expandafter\loi_first\else\expandafter\loi_second\fi}
+\long\def\loi_ifempty#1{\loi_exparg\loi_ifx{\expandafter\relax\detokenize{#1}\relax}}
+\def\loi_ifstar#1#2{\def\loi_ifstar_a{\loi_ifx{*\loi_nxttok}{\loi_first{#1}}{#2}}\futurelet\loi_nxttok\loi_ifstar_a}
+\long\def\loi_ifstuffexpandable#1{\def\loi_tempa{#1}\loi_exparg{\def\loi_tempb}{#1}\expandafter\unless\loi_ifx{\loi_tempa\loi_tempb}}
+\long\def\loi_ifcsexpandable#1{% #1 est-il constitué d'une sc _développable_ ?
+ \loi_ifempty{#1}
+ {\loi_second
+ }
+ {\loi_ifspacefirst{#1}
+ {\loi_second% si espace en 1er, faux
+ }
+ {%
+ \loi_exparg\loi_ifempty{\loi_gobarg#1}% 1 seul token ?
+ {\begingroup\escapechar`\_\def\_{#1}\expandafter\endgroup
+ \csname loi_\if\expandafter\expandafter\expandafter\loi_firsttonil\expandafter\string\_\_nil\string _first\else second\fi\endcsname
+ {\loi_ifstuffexpandable{#1}}
+ {\loi_second}%
+ }
+ {\loi_second% si plusieurs tokens, faux
+ }%
+ }%
+ }%
+}
+\def\loi_ifinrange#1[[#2:#3]]{\loi_ifnum{\numexpr(#1-#2)*(#1-#3)>0 }\loi_second\loi_first}
+\def\loi_ifstring#1\in#2{% si la chaine #1 est contenue dans #2
+ \def\loi_ifstring_a##1#1##2\_nil{\loi_ifempty{##2}\loi_second\loi_first}%
+ \loi_ifstring_a#2#1\@nil% appel de la macro auxiliaire
+}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%% macros \loi_foreach %%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\newcount\loi_cnt_foreach_nest \loi_cnt_foreach_nest=0
+\def\end_foreach{\end_foreach}
+\def\loi_def_foreachsep#1{%
+ \long\def\loi_foreach##1\in##2##3{%
+ \global\advance\loi_cnt_foreach_nest1
+ \loi_argcsname\def{loop_code_\number\loi_cnt_foreach_nest}{##3}%
+ \loi_foreach_a##1##2#1\end_foreach#1%
+ \loi_argcsname\let{loop_code_\number\loi_cnt_foreach_nest}\empty
+ \global\advance\loi_cnt_foreach_nest-1
+ }%
+ \long\def\loi_foreach_a##1##2#1{%
+ \def##1{##2}%
+ \loi_ifx{\end_foreach##1}
+ {}
+ {\csname loop_code_\number\loi_cnt_foreach_nest\endcsname% exécute le code
+ \loi_foreach_a##1%
+ }%
+ }%
+}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%% macros gérant l'appariement %%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\long\def\defpair#1{%
+ \let\loi_listofpair\empty
+ \loi_ifempty{#1}
+ {}
+ {\defpair_a{}#1\loi_quark\loi_quark}%
+}
+\long\def\defpair_a#1#2#3{%
+ \loi_ifx{\loi_quark#2}
+ {\def\loi_sanitizelist##1,\_nil{\def\loi_listofpair{##1}}%
+ \loi_sanitizelist#1\_nil
+ }
+ {\loi_if_validpair#2#3%
+ {\long\def\loi_paired_a{#2}\long\def\loi_paired_b{#3}%
+ \loi_ifx{\loi_paired_a\loi_paired_b}
+ {\loi_error{Paired tokens must not be equal, the pair \detokenize{#2#3} is ignored}%
+ \defpair_a{#1}%
+ }
+ {\defpair_a{#1#2#3,}%
+ }%
+ }
+ {\loi_error{Invalid paired tokens, the pair "\detokenize{#2}" and "\detokenize{#3}" is ignored}%
+ \defpair_a{#1}%
+ }%
+ }%
+}
+\long\def\loi_if_validpair#1#2{%
+ \def\loi_validpair{1}%
+ \loi_if_invalid_pairtoken{#1}{\def\loi_validpair{0}}%
+ \loi_if_invalid_pairtoken{#2}{\def\loi_validpair{0}}%
+ \loi_ifnum{\loi_validpair=1 }
+}
+\long\def\loi_if_invalid_pairtoken#1{%
+ \loi_ifempty{#1}
+ {\loi_identity
+ }
+ {\loi_ifspacefirst{#1}
+ {\loi_identity
+ }
+ {\loi_exparg\loi_ifempty{\loi_gobarg#1}% 1 seul token ?
+ {\ifcat\relax\noexpand#1\expandafter\loi_identity\else\expandafter\loi_gobarg\fi}
+ {\loi_identity}% si plusieurs tokens, faux
+ }%
+ }%
+}
+\long\def\loi_count_occur#1\in#2:#3{% compte le nombre d'occurrences de #1 dans #2 et met le résultat dans la macro #3
+ \long\def\loi_count_occur_a##1##2#1##3\_nil{%
+ \loi_ifempty{##3}
+ {\def#3{##1}}
+ {\expandafter\loi_count_occur_a\number\numexpr##1+1\relax##3\_nil}%
+ }%
+ \loi_count_occur_a0#2#1\_nil
+}
+\long\def\loi_check_pair#1#2\in#3{% teste l'appariement de #1 et #2 dans #3
+ \loi_ifempty{#3}
+ {\loi_second
+ }
+ {\loi_count_occur#1\in#3:\loi_tempa
+ \loi_count_occur#2\in#3:\loi_tempb
+ \loi_ifnum{\loi_tempa=\loi_tempb\relax}%
+ }%
+}
+\long\def\loi_grabpaired_expr#1#2#3#4#5{% #1=liste de paires #2=expression #3=séparateur #4=résultat #5=ce qui reste
+ \let#4\empty
+ \def\loi_remain{#2#3}%
+ \loi_foreach\loi_pair\in{#1}{\expandafter\loi_grabpaired_expr_a\loi_pair{#3}#4}%
+ \def\loi_remove_lastsep##1#3\_nil{\def#4{##1}}%
+ \expandafter\loi_remove_lastsep#4\_nil
+ \expandafter\long\expandafter\def\expandafter\loi_grab_remain#4##1\_nil{\loi_ifempty{##1}{\let#5\empty}{\loi_exparg{\def#5}{\loi_gobarg##1}}}%
+ \loi_grab_remain#2\_nil
+}
+\long\def\loi_grabpaired_expr_a#1#2#3#4{% #1#2=paire en cours #3=séparateur #4=résultat
+ \loi_exparg{\loi_check_pair#1#2\in}#4% si les paires sont appariées dans le résultat
+ {}% passer à la paire suivante
+ {\long\def\loi_grabpaired_expr_b##1#3##2\_nil{%
+ \loi_addtomacro#4{##1#3}% ajouter au résultat ce qui est jusqu'au prochain séparateur
+ \def\loi_remain{##2}%
+ \loi_exparg{\loi_check_pair#1#2\in}{#4}
+ {}
+ {\loi_ifempty{##2}
+ {\loi_error{"\detokenize{#1}" and "\detokenize{#2}" are not paired}}
+ {\loi_grabpaired_expr_b##2\_nil}%
+ }%
+ }%
+ \expandafter\loi_grabpaired_expr_b\loi_remain\_nil
+ }%
+}
+\def\insidepair#1#2#3#4{% #1#2=paire #3=expr #4=macro reçevant le resultat
+ \loi_if_validpair#1#2%
+ {\loi_ifcsexpandable{#3}
+ {\loi_exparg{\insidepair#1#2}{#3}#4%
+ }
+ {\loi_check_pair#1#2\in{#3}% si les paires sont appariées dans le résultat
+ {\def\insidepair_a##1#1##2\_nil{\insidepair_b##2\_nil{#1}}%
+ \def\insidepair_b##1#2##2\_nil##3{%
+ \loi_check_pair#1#2\in{##3##1#2}
+ {\loi_exparg{\def#4}{\loi_gobarg##3##1}}%
+ {\insidepair_b##2\_nil{##3##1#2}}%
+ }%
+ \insidepair_a#3\_nil
+ }
+ {\loi_error{"\detokenize{#1}" and "\detokenize{#2}" are not paired in "#3"}%
+ }%
+ }%
+ }
+ {\loi_error{Invalid paired tokens "\detokenize{#1}" and "\detokenize{#2}", empty \string#4 returned}% et bim
+ \let#4\empty% voilà, bien fait pour vos gueules
+ }%
+}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%% macro \loi_fornum %%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\def\loi_fornum#1=#2to#3\do{%
+ \edef#1{\number\numexpr#2}\edef\loi_sgncmp{\ifnum#1<\numexpr#3\relax>+\else<-\fi}%
+ \expandafter\loi_fornum_a\csname loi_fornum_\string#1\expandafter\endcsname\expandafter{\number\numexpr#3\expandafter}\loi_sgncmp#1%
+}
+\long\def\loi_fornum_a#1#2#3#4#5#6{\def#1{\unless\ifnum#5#3#2\relax\loi_antefi{#6\edef#5{\number\numexpr#5#41\relax}#1}\fi}#1}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%% macro retirant les espaces extrêmes %%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\long\def\loi_ifspacefirst#1{\expandafter\loi_ifspacefirst_a\detokenize{#10} \_nil}
+\long\def\loi_ifspacefirst_a#1 #2\_nil{\loi_ifempty{#1}}
+\expandafter\def\expandafter\loi_gobspace\space{}
+\def\loi_removefirstspaces{\romannumeral\loi_removefirstspaces_a}
+\long\def\loi_removefirstspaces_a#1{\loi_ifspacefirst{#1}{\expandafter\loi_removefirstspaces_a\expandafter{\loi_gobspace#1}}{\loi_stop#1}}
+\edef\loi_restorezerocatcode{\catcode0=\number\catcode0 \relax}
+\catcode0 12
+\long\def\loi_removelastspaces#1{\romannumeral\loi_removelastspaces_a#1^^00 ^^00\_nil}
+\long\def\loi_removelastspaces_a#1 ^^00{\loi_removelastspaces_b#1^^00}
+\long\def\loi_removelastspaces_b#1^^00#2\_nil{\loi_ifspacefirst{#2}{\loi_removelastspaces_a#1^^00 ^^00\_nil}{\loi_stop#1}}
+\loi_restorezerocatcode
+\long\def\loi_removeextremespaces#1{% #1=texte où les espaces extrêmes sont retirés
+ \romannumeral\expandafter\expandafter\expandafter\loi_removelastspaces\expandafter\expandafter\expandafter
+ {\expandafter\expandafter\expandafter\loi_stop\loi_removefirstspaces{#1}}%
+}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%% macro publique \setsepchar %%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\def\setsepchar{\futurelet\loi_nxttok\setsepchar_a}
+\def\setsepchar_a{\loi_ifx{[\loi_nxttok}\setsepchar_b{\setsepchar_b[/]}}
+\long\def\setsepchar_b[#1]#2{% #1=sepcar de <liste des sepcar> #2=<liste des sepcar>
+ \loi_ifempty{#1}
+ {\loi_error{Empty separator not allowed, separator "/" used}%
+ \setsepchar_b[/]{#2}%
+ }
+ {\def\loi_currentsep{#1}%
+ \_removeextremespacesfalse
+ \loi_nestcnt1 % réinitaliser niveau initial à 1
+ \def\nestdepth{1}%
+ \loi_argcsname\let{loi_previndex[\number\loi_nestcnt]}\empty
+ \def\loi_listname{loi_listofsep}%
+ \let\loi_def\def \let\loi_edef\edef \let\loi_let\let
+ \let\loi_listofpair_saved\loi_list_ofpair
+ \let\loi_list_ofpair\empty
+ \loi_ifempty{#2}
+ {\loi_error{Empty list of separators not allowed, "," used}%
+ \readlist_e1{,}%
+ }
+ {\readlist_e1{#2}%
+ }%
+ \loi_argcsname\let\nestdepth{loi_listofseplen[0]}%
+ \loi_argcsname\let\loi_currentsep{loi_listofsep[1]}% 1er car de séparation
+ \let\loi_listofpair\loi_listofpair_saved
+ }%
+}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%% macro normalisant l'index %%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\def\loi_normalizeindex#1#2#3{% #1=macroname #2=liste d'index #3=profondeur max --> renvoie {err}{indx norm}
+ \loi_ifempty{#2}
+ {\loi_stop{}{}}
+ {\loi_normalizeindex_a1{}{#3}{#1}#2,\loi_quark,}%
+}%
+\def\loi_normalizeindex_a#1#2#3#4#5,{% #1=compteur de profondeur #2=index précédents #3=profondeur max #4=macroname #5=index courant
+ \loi_ifx{\loi_quark#5}
+ {\loi_normalizeindex_c#2\loi_quark% supprimer la dernière virgule
+ }
+ {\loi_ifnum{#1>#3 }
+ {\loi_invalidindex{Too deeply nested index, index [.] retained}{#2}% si profondeur trop grande
+ }
+ {\loi_ifinrange\ifnum\numexpr#5<0 -1*\fi(#5)[[1:\csname #4len[#20]\endcsname]]% si abs(#5) hors de [1,len]
+ {\loi_exparg\loi_normalizeindex_b{\number\numexpr#5\ifnum\numexpr#5<0 +\csname #4len[#20]\endcsname+1\fi}{#1}{#2}{#3}{#4}}
+ {\loi_invalidindex{#5 is an invalid index, index [.] retained}{#2}}%
+ }%
+ }%
+}
+\def\loi_normalizeindex_b#1#2#3{\loi_exparg\loi_normalizeindex_a{\number\numexpr#2+1}{#3#1,}}% #1=index à rajouter #2=compteur de profondeur #3=index précédents
+\def\loi_normalizeindex_c#1,\loi_quark{\loi_stop{}{#1}}
+\def\loi_invalidindex#1#2{\loi_ifempty{#2}{\loi_invalidindex_a{#1},}\loi_invalidindex_a{#1}{#2}}
+\def\loi_invalidindex_a#1#2{\loi_invalidindex_b#1\loi_quark#2\loi_quark}
+\def\loi_invalidindex_b#1[.]#2\loi_quark#3,\loi_quark#4\loi_quark,{\loi_stop{#1[#3]#2}{#3}}% #4= index ignorés
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%% macro publique \readlist %%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\newcount\loi_nestcnt
+\def\greadlist{\let\loi_def\gdef\let\loi_edef\xdef\def\loi_let{\global\let}\readlist_a}%
+\def\readlist{\let\loi_def\def\let\loi_edef\edef\let\loi_let\let\readlist_a}
+\def\readlist_a{%
+ \loi_nestcnt1 % niveau initial = 1
+ \loi_argcsname\let{loi_previndex[\number\loi_nestcnt]}\empty
+ \loi_ifstar{\_removeextremespacestrue\readlist_b}{\_removeextremespacesfalse\readlist_b}%
+}
+\long\def\readlist_b#1#2{% #1=macro stockant les éléments #2=liste des éléments
+ \loi_ifcsexpandable{#2}
+ {\loi_exparg{\readlist_b#1}{#2}%
+ }
+ {\loi_edef\loi_listname{\loi_macroname#1}%
+ \loi_argcsname\loi_let{\loi_listname nest}\nestdepth
+ \loi_argcsname\loi_def{\loi_listname[]}{#2}% la liste entière
+ \loi_argcsname\loi_def{\loi_listname sep[]}{}% séparateur vide
+ \loi_ifempty{#2}
+ {\loi_def#1[##1]{}%
+ \loi_argcsname\loi_def{\loi_listname len}{0}\loi_argcsname\loi_def{\loi_listname len[0]}{0}%
+ \loi_error{Empty list ignored, nothing to do}%
+ }
+ {\loi_edef#1[##1]{\unexpanded{\romannumeral\expandafter\loi_checkindex\romannumeral\loi_normalizeindex}{\loi_listname}{##1}{\csname\loi_listname nest\endcsname}{\loi_listname}}%
+ \loi_argcsname\loi_edef{\loi_listname sep}[##1]{\unexpanded{\romannumeral\expandafter\loi_checkindex\romannumeral\loi_normalizeindex}{\loi_listname}{##1}{\csname\loi_listname nest\endcsname}{\loi_listname sep}}%
+ \readlist_c{#2}%
+ \loi_argcsname\loi_argcsname\loi_let{\loi_listname len}{\loi_listname len[0]}% longueur du niveau 0
+ }%
+ }%
+}
+\def\loi_checkindex#1#2#3{%
+ \expandafter\expandafter\expandafter\loi_stop\csname#3[#2]\expandafter\endcsname
+ \romannumeral\loi_ifempty{#1}{\loi_stop}{\loi_stop\loi_error{#1}}%
+}
+\def\readlist_c{%
+ \loi_argcsname\loi_let\loi_currentsep{loi_listofsep[\number\loi_nestcnt]}%
+ \expandafter\readlist_d\loi_currentsep||\_nil
+}
+\long\def\readlist_d#1||#2\_nil#3{\readlist_e1{#3#1}}% #1=<sep courant simple> #3=liste -> rajoute un élément vide pour le test \ifempty ci dessous
+\long\def\readlist_e#1#2{% #1=compteur d'index #2=liste d'éléments à examiner terminée par <sep courant simple> >>RIEN laissé après
+ \loi_ifempty{#2}
+ {\loi_argcsname\loi_edef{\loi_listname len[\csname loi_previndex[\number\loi_nestcnt]\endcsname0]}{\number\numexpr#1-1\relax}%
+ \loi_argcsname\loi_let{\loi_listname sep[\csname loi_previndex[\number\loi_nestcnt]\endcsname\number\numexpr#1-1\relax]}\empty% le dernier <sep> est <vide> ##NEW v1.52
+ \advance\loi_nestcnt-1
+ \loi_argcsname\loi_let\loi_currentsep{loi_listofsep[\number\loi_nestcnt]}%
+ }
+ {\loi_expafter{\readlist_f{#2}{}}\loi_currentsep||\loi_quark||#2\_nil{#1}% aller isoler le 1er item
+ }%
+}
+\long\def\readlist_f#1#2#3||{% #1=liste restante #2=<dernier sep utilisé> #3=<sep courant>
+ \loi_ifx{\loi_quark#3}% on a épuisé tous les <séparateurs> ? RESTE à lire <expr+sep1>\_nil{<compteur>}
+ {\loi_ifempty{#2}% si #2 vide, aucun <sep utilisé> n'a été trouvé, il reste à lire "<liste complète>\_nil"
+ {\long\def\readlist_g##1\_nil##2{\loi_exparg{\readlist_h{##2}{}}{\loi_gobarg##1}{#2}}% ##2=compteur d'index
+ }
+ {\loi_ifx{\loi_listofpair\empty}% paires définies ?
+ {\long\def\readlist_g##1#2##2\_nil##3{\loi_exparg{\readlist_h{##3}{##2}}{\loi_gobarg##1}{#2}}%
+ }
+ {\long\def\readlist_g##1\_nil##2{%
+ \loi_exparg{\loi_exparg\loi_grabpaired_expr\loi_listofpair}{\loi_gobarg##1}{#2}\loi_grabpaired_result\loi_grabpaired_remain
+ \loi_exparg{\loi_exparg{\readlist_h{##2}}{\loi_grabpaired_remain}}{\loi_grabpaired_result}{#2}}%
+ }%
+ }%
+ \readlist_g\relax% le \relax meuble l'argument délimité
+ }
+ {\long\def\readlist_g##1#3##2\_nil{%
+ \loi_ifempty{##2}% si <liste restante> ne contient pas le <sep courant>
+ {\readlist_f{#1}{#2}% recommencer avec le même <sep utile>
+ }%
+ {\loi_ifx{\loi_listofpair\empty}% si pas de paires définies
+ {\loi_exparg\readlist_f{\loi_gobarg##1#3}{#3}% raccourcir <liste restante> et <sep courant>:=<sep utile>% ##BUGFIX v1.53
+ }%
+ {\loi_exparg\loi_grabpaired_expr\loi_listofpair{#1}{#3}\loi_grabpaired_result\loi_grabpaired_remain
+ \loi_exparg\readlist_f{\loi_grabpaired_result#3}{#3}%
+ }%
+ }%
+ }%
+ \readlist_g\relax#1#3\_nil% ##BUGFIX v1.53
+ }%
+}
+\long\def\readlist_h#1#2#3{% #1=compteur d'index #2=liste restante #3=élément courant
+ \loi_ifnum{0\loi_exparg\loi_ifspacefirst{\loi_currentsep}{}1\if_removeextremespaces1\fi=11 }% s'il faur retirer les espaces extrêmes
+ {\loi_exparg{\loi_exparg{\readlist_i{#1}{#2}}}{\loi_removeextremespaces{#3}}}% redéfinir l'élément courant
+ {\readlist_i{#1}{#2}{#3}}%
+}
+\long\def\readlist_i#1#2#3#4{% #1=compteur d'index #2=liste restante #3=élément courant #4=sep utilisé
+ \loi_ifnum{0\if_ignoreemptyitems1\fi\loi_ifempty{#3}1{}=11 }
+ {\readlist_e{#1}{#2}% si l'on n'ignore pas les éléments vides
+ }%
+ {\loi_argcsname\loi_def{\loi_listname[\csname loi_previndex[\number\loi_nestcnt]\endcsname#1]}{#3}% assignation de l'item ctuel à la macro
+ \loi_argcsname\loi_def{\loi_listname sep[\csname loi_previndex[\number\loi_nestcnt]\endcsname#1]}{#4}% assignation du <sep> actuel à la macro \<macrolist>sep
+ \loi_ifnum{\loi_nestcnt<\nestdepth\relax}% si imbrication max non atteinte
+ {\advance\loi_nestcnt1
+ \loi_argcsname\edef{loi_previndex[\number\loi_nestcnt]}{\csname loi_previndex[\number\numexpr\loi_nestcnt-1]\endcsname#1,}%
+ \readlist_c{#3}% recommencer avec l'élément courant
+ }
+ {}%
+ \loi_exparg\readlist_e{\number\numexpr#1+1}{#2}% puis chercher l'élément suivant dans la liste restante
+ }%
+}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%% macro \listlen %%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\def\listlen#1[#2]{%
+ \romannumeral\loi_ifempty{#2}
+ {\expandafter\expandafter\expandafter\loi_stop\csname\loi_macroname#1len[0]\endcsname}
+ {\loi_exparg\listlen_a{\romannumeral-`\.\loi_macroname#1}{#2}}%
+}
+\def\listlen_a#1#2{% #1=macro name #2=index non normalisé prendre <profondeur max-1>
+ \loi_exparg{\expandafter\listlen_b\romannumeral\loi_normalizeindex{#1}{#2}}{\number\numexpr\csname#1nest\endcsname-1}{#1}%
+}
+\def\listlen_b#1#2#3{% #1=err #2=index normalisé #3=macroname
+ \expandafter\expandafter\expandafter\loi_stop\csname#3len[#2,0]\expandafter\endcsname
+ \romannumeral\loi_ifempty{#1}{\loi_stop}{\loi_stop\loi_error{#1}}%
+}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%% macro \foreachitem %%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\def\foreachitem#1\in#2{%
+ \edef\foreachitem_a{\noexpand\foreachitem_c\noexpand#1{\expandafter\noexpand\csname\loi_macroname#1cnt\endcsname}{\loi_macroname#2}}%
+ \futurelet\loi_nxttok\foreachitem_b
+}
+\def\foreachitem_b{\loi_ifx{\loi_nxttok[}\foreachitem_a{\foreachitem_a[]}}
+\def\foreachitem_c#1#2#3[#4]{% prendre <profondeur max-1>
+ \loi_exparg{\expandafter\foreachitem_d\romannumeral\loi_normalizeindex{#3}{#4}}{\number\numexpr\csname#3nest\endcsname-1}#1{#2}{#3}%
+}
+\def\foreachitem_d#1#2{\loi_ifempty{#2}{\foreachitem_e{#1}{}}{\foreachitem_e{#1}{#2,}}}% #1=err #2=index norm
+\long\def\foreachitem_e#1#2#3#4#5#6{% #1=err #2=index norm #3=macroiter #4=compteur associé #5=nom de macrolist #6=code
+ \loi_ifnum{\csname#5len[#20]\endcsname>0 }
+ {\loi_ifempty{#1}{}{\loi_error{#1}}%
+ \loi_fornum#4=1to\csname#5len[#20]\endcsname\do{\loi_argcsname\let#3{#5[#2#4]}#6}%
+ }
+ {}%
+}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%% macro \showitem %%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\def\showitems{\loi_ifstar{\let\showitems_cmd\detokenize\showitems_a}{\let\showitems_cmd\loi_identity\showitems_a}}
+\def\showitems_a#1{\def\showitems_b{\showitems_d#1}\futurelet\loi_nxttok\showitems_c}
+\def\showitems_c{\loi_ifx{\loi_nxttok[}\showitems_b{\showitems_b[]}}
+\def\showitems_d#1[#2]{\foreachitem\showitems_ater\in#1[#2]{\showitemsmacro{\expandafter\showitems_cmd\expandafter{\showitems_ater}}}}
+\unless\ifdefined\fbox
+ \newdimen\fboxrule \newdimen\fboxsep \fboxrule=.4pt \fboxsep=3pt % réglages identiques à LaTeX
+ \def\fbox#1{% imitation de la macro \fbox de LaTeX, voir pages 271 à 274 de "Apprendre à programmer en TeX"
+ \hbox{%
+ \vrule width\fboxrule
+ \vtop{%
+ \vbox{\hrule height\fboxrule \kern\fboxsep \hbox{\kern\fboxsep#1\kern\fboxsep}}%
+ \kern\fboxsep \hrule height\fboxrule
+ }\vrule width\fboxrule
+ }%
+ }
+\fi
+\def\showitemsmacro#1{% encadrement par défaut
+ \begingroup\fboxsep=0.25pt \fboxrule=0.5pt \fbox{\strut#1}\endgroup
+ \hskip0.25em\relax
+}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%% macro \itemtomacro %%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\def\itemtomacro#1[#2]{% #1[#2]=item non encore lu: #3=macro
+ \edef\loi_listname{\loi_macroname#1}%
+ \loi_exparg{\expandafter\itemtomacro_a\romannumeral\expandafter\loi_normalizeindex\expandafter{\loi_listname}{#2}}{\csname\loi_listname nest\endcsname}\let
+}
+\def\gitemtomacro#1[#2]{% #1[#2]=item
+ \xdef\loi_listname{\loi_macroname#1}%
+ \loi_exparg{\expandafter\itemtomacro_a\romannumeral\expandafter\loi_normalizeindex\expandafter{\loi_listname}{#2}}{\csname\loi_listname nest\endcsname}{\global\let}%
+}
+\def\itemtomacro_a#1#2#3#4{%
+ \loi_ifempty{#1}{}{\loi_error{#1}}%
+ \loi_argcsname#3#4{\loi_listname[#2]}%
+}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%% réglages par défaut %%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\newif\if_removeextremespaces
+\newif\if_ignoreemptyitems
+\let\ignoreemptyitems\_ignoreemptyitemstrue
+\let\reademptyitems\_ignoreemptyitemsfalse
+\setsepchar{,}
+\defpair{}
+\loi_def_foreachsep{,}
+\reademptyitems
+
+\loi_restorecatcode
+\endinput
+
+######################################################################
+############################ Historique #############################
+######################################################################
+
+v1.0 19/8/2016
+ - Première version publique
+
+v1.1 01/09/2016
+ - Stockage des séparateurs dans <macrolist>sep
+ - bug corrigé dans \loi_restorecatcode
+
+v1.2 22/10/2016
+ - macros \greadlist et \gitemtomacro pour la globalité
+
+v1.3 18/11/2016
+ - bugs corrigés dans la gestion de la globalité
+
+v1.4 05/10/2017
+ - test \loi_ifprimitive ajouté au test \loi_ifcs
+ - suppression de \loi_expafternil, création de \loi_expafter,
+ modification de \loi_argcsname
+ - correction d'un bug : \setsepchar{\par} ne provoque plus
+ d'erreur. \loi_ifnum devient \long
+
+v1.5 06/10/2017
+ - correction d'un bug dans \loi_ifcs
+
+v1.51 24/10/2017
+ - correction d'un bug dans \loi_ifcs
+
+v1.52 13/01/2018
+ - le dernier séparateur est <vide>
+
+v1.53 13/03/2018
+ - correction d'un bug dans \readlist_g
+
+v1.6 01/11/2018
+ - possibilité d'appariement de tokens dans les items
+
+v1.61 03/03/2019
+ - la macro \loi_ifcs contient une erreur de conception.
+ Il faut tester si le token est un sc && s'il est
+ développable pour renvoyer vrai car il existe des sc
+ non développables && qui ne sont _pas_ des primitives.
+ Macro rebaptisée \loi_ifcsexpandable \ No newline at end of file