diff options
author | Karl Berry <karl@freefriends.org> | 2009-08-15 23:34:56 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2009-08-15 23:34:56 +0000 |
commit | 27f9cb520563a0b8df6d876f02cdb267be5b6116 (patch) | |
tree | 9ad3871f8a40fcf6450053e16e3f6f8b1addfb8a /Master/texmf-dist | |
parent | bf8d9b1bb7480816950fe25c98685724d843378e (diff) |
etextools update (15aug09)
git-svn-id: svn://tug.org/texlive/trunk@14694 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist')
-rw-r--r-- | Master/texmf-dist/doc/latex/etextools/etextools-examples.pdf | bin | 79220 -> 80209 bytes | |||
-rw-r--r-- | Master/texmf-dist/doc/latex/etextools/etextools-examples.tex | 97 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/etextools/etextools.pdf | bin | 564537 -> 635108 bytes | |||
-rw-r--r-- | Master/texmf-dist/source/latex/etextools/etextools.dtx | 1047 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/etextools/etextools.ins | 5 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/etextools/etextools.sty | 354 |
6 files changed, 1222 insertions, 281 deletions
diff --git a/Master/texmf-dist/doc/latex/etextools/etextools-examples.pdf b/Master/texmf-dist/doc/latex/etextools/etextools-examples.pdf Binary files differindex 2ed2e95f2c5..3906cf7c21e 100644 --- a/Master/texmf-dist/doc/latex/etextools/etextools-examples.pdf +++ b/Master/texmf-dist/doc/latex/etextools/etextools-examples.pdf diff --git a/Master/texmf-dist/doc/latex/etextools/etextools-examples.tex b/Master/texmf-dist/doc/latex/etextools/etextools-examples.tex index 97c800e3fe3..572e76e479d 100644 --- a/Master/texmf-dist/doc/latex/etextools/etextools-examples.tex +++ b/Master/texmf-dist/doc/latex/etextools/etextools-examples.tex @@ -21,15 +21,16 @@ %% etextools.sty, etextools.pdf, etextools.ins, %% and etextools-examples.tex %% -%%% etextools : more e-TeX useful tools for LaTeX package writers +%%% etextools : more e-TeX useful tools for LaTeX package writers (v. + \documentclass[11pt,french,a4paper,oneside]{scrartcl} \usepackage[latin1]{inputenc} \usepackage[T1]{fontenc} \usepackage[american]{babel} -\usepackage{geometry,doc,ltxdockit,txfonts,fancyhdr} +\usepackage{geometry,doc,ltxdockit,txfonts,fancyhdr,stmaryrd,graphicx,fancyvrb} \usepackage{etextools} \hypersetup{colorlinks,pdfstartview={FitH}} -\geometry{top=2cm,bottom=2cm,left=2.5cm,right=1cm} +\geometry{top=1.5cm,bottom=1.2cm,left=2.5cm,right=1cm} \fancyhf{} \fancyhead[L]{Examples for the \sty{etextools} package} \pagestyle{fancy} @@ -37,6 +38,9 @@ \makeatletter \def\smex{\leavevmode\hb@xt@2em{\hfil$\longrightarrow$\hfil}} +\def\FE{\setbox8\hbox{$\m@th\bindnasrepma$}% + \textcolor{fecc}{\scalebox{2}{$\copy8\mkern-13.5mu\copy8\mkern-13.5mu\copy8$}}} +\definecolor{fecc}{rgb}{.2,.6,.2} \def\strip@meaning{\expandafter\strip@prefix\meaning} \def\strip@macro{\expandafter\strip@macroprefix\meaning} \def\get@params#1{\expandafter\@get@params\meaning#1\@nil} @@ -49,12 +53,14 @@ \def\meaningcs#1{\expandafter\meaning\csname#1\endcsname} \def\Meaningcs#1{\expandafter\strip@meaning\csname #1\endcsname} +\@ifundefined{pdfstrcmp}{\let\ifpdfTeX\iffalse}{\let\ifpdfTeX\iftrue} -\newcommand\test[1]{% +\newcommand*\test{\@ifstar{\let\fe\relax\testi}{\let\fe\FE\testi}} +\newcommand\testi[1]{% \csname test#1\endcsname \edef\usercmd{\Meaningcs{test#1}}\edef\result{\meaningcs{#1Test}}\noindent \begin{tabular}{lp{15cm}} - \multicolumn{2}{l}{\textcolor{blue}{\llap\smex\tt \usercmd}} \\[1.5ex] + \multicolumn{2}{l}{\textcolor{blue}{\llap{\fe\,\smex}\tt \usercmd}} \\[1.5ex] \cmd{#1Test}= & \tt\bfseries\result \end{tabular}\par\nobreak\hrulefill\null\goodbreak} @@ -157,7 +163,9 @@ \test{FE@testopt} \section{Lists management} + \subsection{\cmd{csvloop} and \cmd{csvloop*} examples} + \subsubsection{\cmd{makequotes}} \def\makequotes#1{"#1"\space} \def\testcsvloop{% @@ -165,11 +173,13 @@ } \preline\makequotes \test{csvloop} + \subsubsection{\cmd{detokenize}} \def\testcsvloop{% \edef\csvloopTest{\csvloop*[\detokenize]{\un,\deux}} }\hrulefill\par \test{csvloop} + \subsubsection{\cmd{numexpr}} \def\mylist{1,2,3,4,5}\def\BySeven#1{$#1\times 7 = \number\numexpr#1*7\relax$\par} \def\testcsvloop{% @@ -177,26 +187,91 @@ \preline\mylist \preline*\BySeven \test{csvloop} + \subsubsection{protected \cmd{textbf}} \def\testcsvloop{% \protected@edef\csvloopTest{\csvloop*[\textbf]{hello ,my ,friends}} }\hrulefill\par \test{csvloop} -\subsection{\cmd{getlistitem}} +\subsection{Index in lists and items by index} + +\subsubsection{\cmd{getlistitem}} \csvtolist*\mylist{one,two,three,four,five,alpha,beta,gamma} \def\testgetlistitem{% - \edef\getlistitemTest{\getlistitem\mylist{4}} + \edef\getlistitemTest{\getlistitem{4}\mylist} }\hrulefill\par \noindent\hskip6pt|\csvtolist*\mylist{one,two,three,four,five,alpha,beta,gamma}|\par\vskip1.5ex \test{getlistitem} -\subsection{\cmd{getlistindex} {\mdseries(not expandable)}} -\getlistindex{four}\mylist +\subsubsection{\cmd{getlistindex}} +\ifpdfTeX +\leavevmode\vadjust{\textsl{Require the }\string\pdfstrcmp\ \textsl{primitive (pdf\TeX{}) :}} +\def\testgetlistindex{% + \edef\getlistindexTest{\getlistindex{alpha}\mylist} +}\hrulefill\par +\noindent\hskip6pt|\csvtolist*\mylist{one,two,three,four,five,alpha,beta,gamma}|\par\vskip1.5ex +\test{getlistindex} + +\leavevmode\vadjust{\textsl{Require the }\string\pdfstrcmp\ \textsl{primitive (pdf\TeX{}) :}} +\def\testgetlistindex{% + \edef\getlistindexTest{\getcsvlistindex*{alpha}{one,two,three,four,five,alpha,beta}} +}\hrulefill\par +\test{getlistindex} +\fi + \hrulefill\par +\getlistindex[\myindex]{alpha}\mylist +{\color{blue}\noindent\hskip6pt\llap\smex|\getlistindex[\myindex]{alpha}\mylist|\par\vskip1.5ex} +{\tt\string\myindex=\quad\textbf{\meaning\myindex}} +\hrulefill\par\vskip.5ex + +\hrulefill\par +\newcount\myindex +\getcsvlistindex*[\myindex]{alpha}{one,two,three,four,five,alpha,beta} +\noindent\hskip6pt|\newcount\myindex|\par +{\color{blue}\noindent\hskip6pt\llap\smex|\getcsvlistindex*[\myindex]{alpha}{one,two,three,four,five,alpha,beta}|}\par\vskip.5ex +{\tt\string\the\string\myindex=\qquad\textbf{\the\myindex}} +\hrulefill\par\vskip.5ex + +\subsubsection{\cmd{xgetlistindex}} +\ifpdfTeX +\leavevmode\vadjust{\textsl{Require the }\string\pdfstrcmp\ \textsl{primitive (pdf\TeX{}) :}} +\def\x{beta} +\def\testxgetlistindex{% + \edef\xgetlistindexTest{\xgetlistindex{\x}\mylist} +}\hrulefill\par \noindent\hskip6pt|\csvtolist*\mylist{one,two,three,four,five,alpha,beta,gamma}|\par\vskip1.5ex -\noindent\hskip6pt\textcolor{blue}{\llap\smex\cmd{getlistindex}\string{four\string}\cmd{mylist}}\par\vskip1.5ex -\noindent\hskip6pt\cmd{indexinlist}=\quad{\bfseries\meaning\indexinlist}\par\hrulefill\par +\preline*\x +\test{xgetlistindex} +\fi + +\subsubsection{\cmd{getlistindex} with \cmd{ifcase}} + +\leavevmode\vadjust{Always purely expandable (no need of |\pdfstrcmp|, comparison done by |\ifx|):} +\hrulefill\par\noindent +\llap{\FE\,\smex}\par\vskip-2.5\baselineskip\strut +\begin{Verbatim} + \ifcase \gettokslistindex*{D}{LRDF\relax O} + Problem + \or What do to if L + \or What do to if R + \or What do to if D + \or What do to if F + \or What do to if \relax + \or What do to if O + \fi +\end{Verbatim} + +{\tt Result=\qquad\bfseries +\ifcase\gettokslistindex*{D}{LRDF} + Problem +\or What do to if L +\or What do to if R +\or What do to if D +\or What do to if F +\fi}\par +\hrulefill\par\vskip.5ex \end{document} diff --git a/Master/texmf-dist/doc/latex/etextools/etextools.pdf b/Master/texmf-dist/doc/latex/etextools/etextools.pdf Binary files differindex 1a20a8f26f6..5e82e254a98 100644 --- a/Master/texmf-dist/doc/latex/etextools/etextools.pdf +++ b/Master/texmf-dist/doc/latex/etextools/etextools.pdf diff --git a/Master/texmf-dist/source/latex/etextools/etextools.dtx b/Master/texmf-dist/source/latex/etextools/etextools.dtx index 3c335b7296d..6dded5c5e0a 100644 --- a/Master/texmf-dist/source/latex/etextools/etextools.dtx +++ b/Master/texmf-dist/source/latex/etextools/etextools.dtx @@ -1,5 +1,5 @@ % \iffalse meta-comment -%%% etextools : more e-TeX useful tools for LaTeX package writers +%%% etextools : more e-TeX useful tools for LaTeX package writers (v. % % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either @@ -37,7 +37,7 @@ \input docstrip.tex \Msg{************************************************************************} \Msg{* Installation} -\Msg{* Package: etextools 2009/07/14 v2e e-TeX more useful tools for LaTeX package writers} +\Msg{* Package: etextools 2009/07/14 v2h e-TeX more useful tools for LaTeX package writers} \Msg{************************************************************************} \keepsilent @@ -96,17 +96,17 @@ and etextools-examples.tex \documentclass[a4paper,oneside]{ltxdockit} \usepackage[latin9]{inputenc} \usepackage[american]{babel} -\usepackage{doc,tocloft,stmaryrd,amsmath,graphics,geometry,fancyhdr,framed,bbding,trace,embedfile,etoolbox,marvosym} +\usepackage{doc,tocloft,stmaryrd,amsmath,graphics,geometry,fancyhdr,framed,bbding,trace,embedfile,etoolbox,marvosym,fancyvrb} \CodelineNumbered\CodelineIndex \embedfile{\thisfile.dtx} -\geometry{left=4.5cm,marginparwidth=14pt,right=2cm,totalheight=26cm} +\geometry{left=4.5cm,marginparwidth=14pt,right=2cm,totalheight=26.5cm} \titlepage{% title={The \sty{etextools} package}, subtitle={An \etex package providing useful tools for LaTeX Users \\ and package Writers}, url={http://www.ctan.org/tex-archive/macros/latex/contrib/etextools/}, author={Florent CHERVET}, email={florent.chervet@free.fr}, - revision={2\:$\boldsymbol{\zeta}$}, + revision={2\:$\boldsymbol{\eta}$}, date={12 août 2009}} \hypersetup{% hyperindex=true, @@ -122,7 +122,7 @@ and etextools-examples.tex %</driver> % \fi % -% \CheckSum{887} +% \CheckSum{0} % % \CharacterTable % {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z @@ -210,20 +210,29 @@ and etextools-examples.tex % \hbox{\rlap{\kern.4em\hyperref{}{cmdlabel}{#1}{\colorbox{green}{\textcolor{red}{\SunshineOpenCircled}}}}}}}} % \def\FE{\setbox8\hbox{$\m@th\bindnasrepma$}% % \marginpar{\raisebox{-2pt}{{\fecccolor\scalebox{2}{$\copy8\mkern-13.5mu\copy8\mkern-13.5mu\copy8$}}}}\space} +% \def\pdfFE{\setbox8\hbox{$\m@th\bindnasrepma$}% +% \marginpar{\raisebox{-2pt}{{\fecccolor\llap{\textsf{pdf}\TeX{}\,}\scalebox{2}{$\copy8\mkern-13.5mu\copy8\mkern-13.5mu\copy8$}}}}} +% \def\clap#1{\hb@xt@\z@{\hss#1\hss}} % \def\smex{\leavevmode\hb@xt@2em{\hfil\spotcolor$\longrightarrow$\hfil}} % \font\manual=manfnt\def\dbend{\marginpar{\manual\char127}\space} +% \def\CS#1{\texttt{\expandafter\@gobble\string\\#1}} +% \def\CSbf#1{\textbf{\CS{#1}}} +% \def\Xpackage{\@dblarg\X@package} +% \def\X@package[#1]#2{% +% \sty{#2\footnote{\noindent\sty{#2}: \href{http://www.ctan.org/tex-archive/macros/latex/contrib/#1}{\nolinkurl{CTAN:macros/latex/contrib/#1}}}}} % \parindent\z@\topsep\z@\partopsep\z@\parskip.3\baselineskip % \cftbeforesecskip=4pt % \cftbeforepartskip=11pt % \let\footnoterule\relax +% \footskip=0pt % \lastlinefit999 % \makeatother % % \thispagestyle{plain}\printtitlepage\medskip % \fontfamily{ua1}\selectfont -% \tableofcontents\medskip\enlargethispage{\baselineskip}\thispagestyle{plain} +% \tableofcontents\medskip\thispagestyle{plain}\enlargethispage{2.5\baselineskip} % -% \begin{shaded}\parindent0pt\noindent\large +% \begin{shaded}\parindent0pt\noindent\normalsize\topsep=-\parskip\itemsep=-\parskip % % {\bfseries\catcode`\ \active\let =\,\hfil\NibSolidRight A b s t r a c t \NibSolidLeft\hfil}\par % @@ -236,18 +245,18 @@ and etextools-examples.tex % and the \sty{etoolbox} package from Philipp Lehman. Both of them % are available on CTAN under the \sty{/latex/contrib/} directory \footnotemark. % -% The main contributions of this package are : +% \underline{The main contributions of this package are :} % \begin{itemize} -% \item the \cmdref{expandnext} macro and the \cmdref{ifempty} macro +% \item the \cmdref{expandnext} macro and the \cmdref{ifempty} and \cmdref{xifempty} macros % \item the ability to define fully expandable macros with parameter and/or star version (with a small restriction) % -- see \cmdref{FE@testopt}, \cmdref{FE@ifstar} -% \item a Command-List Parser constructor that fully uses this new feature : command-list parser are fully expandable -% -- see \cmdref{csvloop} and \cmdref{listloop} -% \item three macros that are lacking from the \sty{etoolbox} package for removing elements from lists : +% \item a Command-List Parser constructor that uses this new feature : command-list parsers are fully expandable: +% \cmdref{csvloop}, \cmdref{listloop}, \cmdref{toksloop} and more... +% \item four macros that are lacking from the \sty{etoolbox} package for removing elements from lists : % \cmdref{listdel} and \cmdref{listgdel}, \cmdref{listedel}, \cmdref{listxdel} -% \item macros that return the index of an item in a list: \cmdref{getlistindex} and \cmdref{xgetlistindex} and conversely +% \item get the index of an item in a list: \cmdref{getlistindex} and \cmdref{xgetlistindex} and conversely % the item at a given position in a list: \cmdref{getlistitem} -% +% \item a vectorized form of \cmd{futurelet}: \cmdref{collecttoks} is a standard token scanner. % \end{itemize} % % \end{shaded} @@ -257,7 +266,8 @@ and etextools-examples.tex % \begin{tabbing} % \qquad\=\smex\=To get the documentation, \= run (twice):\quad\= \sty{pdflatex etextools.dtx} \\ % \>\smex\>To get the package, \> run:\> \sty{etex etextools.dtx} -% \end{tabbing}} +% \end{tabbing} +% The .dtx file is embeded in this pdf thank to \sty{embedfile} by H. Oberdiek.} % % \vfil\eject % @@ -372,25 +382,35 @@ and etextools-examples.tex % % |\ifempty|\FE is similar to |\ifblank| but it test if a string is really empty % (it shall not contain any character nor spaces). To test if the replacement -% text of a macro is empty, one may use |\ifempty| in conjunction with |\expandnext|: +% text of a macro is empty, one may use |\ifempty| in conjunction with \cmdref{expandnext}: % \begin{tabbing} % \quad\=|\expandnext\ifempty{\macro}| \prm{true}\prm{false} % \end{tabbing} % +% |\ifempty| is based on |\detokenize| and accept anything in its argument. % -% \cmditem{deblank}{string} \cmdlabel{deblank} \seeimpl{deblank} % -% |\deblank|\FE removes all leading and trailing blank spaces from its argument.\medbreak +% \cmditem{xifempty}{string or cs-token}{true}{false} \cmdlabel{xifempty} \seeimpl{xifempty} % -% \cmditem{xifblank}{string}{true}{false} \seeimpl{xifblank} +% |\xifempty|\pdfFE is similar to |\ifempty| but the argument is expanded during comparison. % -% |\xifblank| is similar to |\ifblank| except that the \prm{string} is first expanded -% with |\protected@edef|.\medbreak +% \begin{tabbing} +% \quad\=|\def\x{\@empty}\def\y{}| \\ +% \>|\xifempty{\x\y}| \prm{true}\prm{false} +% \end{tabbing} % -% \cmditem{xifstrequal}{string1}{string2}{true}{false}\cmdlabel{xifstrequal}\seeimpl{xifstrequal} +% {\rmk The macro is based on the \cs{pdfstrcmp} primitive.} % -% |\xifstrequal| is similar to |\ifstrequal| but each \prm{string} argument -% is expanded with |\protected@edef| before comparison.\medbreak +% \cmditem{ifnotempty}{string}{true}{false} \cmdlabel{ifnotempty}\seeimpl{ifnotempty} +% +% |\ifnotempty|\FE reverses the test of |\ifempty| +% +% +% \cmditem{xifblank}{string}{true}{false} \seeimpl{xifblank} +% +% |\xifblank| is similar to |\ifblank| except that the \prm{string} is first expanded +% with |\protected@edef|. +% \medbreak % % \cmditem{iffirstchar}{string1}{string2}{true}{false} \cmdlabel{iffirstchar}\seeimpl{iffirstchar} % \cmditem*{iffirstchar}{}{string}{true}{false} @@ -400,6 +420,8 @@ and etextools-examples.tex % is expanded before comparison. Example:§ % \qquad|\iffirstchar *{*hello*}{begins with a star}{begins with something else}| % +% Alternatively, you may use the \cmdref{ifstrmatch} test. +% % There is a ``special'' use of this command when one want to test if a \prm{string} begins % with an \emph{escape} character (\,\textbackslash\,) one may say: % \begin{tabbing} @@ -419,6 +441,46 @@ and etextools-examples.tex % % |\ifsinglechar|\FE performs the test |\iffirstchar| but only if \prm{string2} has one single character. % +% Note that there is a small difference if you run on pdf\TeX{} or on another system:§ +% \DeleteShortVerb{\|} +% \hfil +% \begin{tabular}{|c|c|}\hline +% pdf\TeX{} (use \cs{pdfstrcmp}) & Other \\ \hline +% \cs{ifsinglechar} *\{\textvisiblespace*\} is \textbf{false} & \cs{ifsinglechar} *\{\textvisiblespace*\} is \textbf{true} \\ \hline +% \end{tabular}\hfil +% +% \MakeShortVerb{\|} +% But: \cs{ifsinglechar} *\{*\textvisiblespace\}\quad is \textbf{always false}. +% +% +% \cmditem{iflastchar}{string1}{string2}{true}{false} \cmdlabel{iflastchar}\seeimpl{impl:iflastchar} +% +% |\iflastchar| compares the end of \prm{string2} with the totality of \prm{string1} (\prm{string1} is not +% necessarily a single character but the macro has been designed for this purpose first, hence the name). +% +% |\iflastchar| is NOT purely expandable (use \cmdref{ifstrmatch} for purely expandable test). +% +% +% \cmditem{ifstrcmp}{string1}{string2}{true}{false} \cmdlabel{ifstrcmp}\seeimpl{ifstrcmp} +% +% |\ifstrcmp|\pdfFE is the \LaTeX{} form of |\pdfstrcmp| primitive. +% +% Neither \prm{string1} not \prm{string2} is expanded during comparison. The comparison is +% \textit{catcode agnostic} (use of |\detokenize |). +% +% \cmditem{ifstrmatch}{pattern}{string}{true}{false} \cmdlabel{ifstrmatch}\seeimpl{ifstrmatch} +% +% |\ifstrmatch|\pdfFE is based on the |\pdfmatch| primitive that implements POSIX-regex. +% +% You can test the last character of a string in a purely expandable way by: +% \begin{tabbing} +% \quad\=\cs{ifstrmatch}\{[\textasteriskcentered]\$\}\{\prm{string}\} +% \end{tabbing} +% for example to test \raise2pt\hbox{\textasteriskcentered}. +% \end{ltxsyntax} +% +% \section{Fully expandable macros with options} +% \vskip-\baselineskip % Now with the macro |\ifsinglechar| it becomes possible to write fully expandable macros with an option, \textbf{provided % that this macro has at least one non-optional argument}, as far as we don't use |\futurelet| nor any assignation. % The ``trick'' is the following: @@ -430,7 +492,6 @@ and etextools-examples.tex % \> |\def\MacroNoOption#1|...\>\textit{definition} % \end{tabbing} % -% \clearpage % Moreover (in the style of |\@testopt|): % \begin{tabbing} % \qquad\= |\def\MacroWithOption#1{\ifsing|\=|lechar|\=|[{#1}|\\ @@ -438,10 +499,6 @@ and etextools-examples.tex % \>\>|{\MacroHasOption[default]{#1}}}| % \end{tabbing} % -% \end{ltxsyntax} -% -% \section{Fully expandable macros with options} -% % \begin{ltxsyntax} % % \cmditem{FE@testopt}{argument to be tested}{commands}{default option} \cmdlabel{FE@testopt}\seeimpl{FE@testopt} @@ -465,8 +522,21 @@ and etextools-examples.tex % % Remember that |\StarredCommand| and |\NotStarredCommand| \textbf{must have at least one mandatory argument.} % -% % {\rmk |\FE@ifstar| is used in the definitions of \cmdref{DeclareCmdListParser}, \cmdref{csvloop}, \cmdref{listloop} -% and \cmdref{csvtolist}.} +% {\rmk |\FE@ifstar| is used in the definitions of \cmdref{DeclareCmdListParser}, \cmdref{csvloop}, \cmdref{listloop} +% and \cmdref{toksloop}.} +% +% \cmditem{FE@ifchar}{Variant Mark Character}{argument to be tested}{special-commands}{normal-commands}\cmdlabel{FE@ifchar}\seeimpl{FE@ifchar} +% +% As a\FE generalisation of \cs{FE@ifstar} \sty{etextools} provides \cmd{FE@ifchar} for use with other variants than the star-form. +% +% For example, to define a `\,$\boldsymbol{+}$\,` variant: +% \begin{tabbing} +% \qquad\=|\def\SpecialMacro#1{\FE@|\=|ifchar|{+}\=|{#1}|\\ +% \>\>|{\SpecialFormMacro}|\\ +% \>\>|{\NormalFormMacro}}| +% \end{tabbing} +% +% |\SpecialMacro| must have at least one mandatory argument. % % \end{ltxsyntax} % @@ -524,6 +594,8 @@ and etextools-examples.tex % \cmditem*{csvloop*}[auxiliary commands]{item,item,item,...} % \cmditem*{listloop}[auxiliary commands]{listmacro} \cmdlabel{listloop} % \cmditem*{listloop*}[auxiliary commands]{expanded list} +% \cmditem{toksloop}[auxiliary commands]{tokenslistmacro} \cmdlabel{toksloop} +% \cmditem*{toksloop*}[auxiliary commands]{list of tokens} % % |\listloop|\FE acts exactly as \sty{etoolbox}-|\dolistloop| with an optional argument to change % the default auxiliary command |\do| to apply to each item of the list : @@ -533,6 +605,9 @@ and etextools-examples.tex % \>\>\> |\expandafter\docsvlist\expandafter{\csvlist}| % \end{tabbing} % +% The token list is a list without delimiter. +% +% % % \subsection{Converting csv lists to \sty{etoolbox}-lists} % @@ -548,8 +623,23 @@ and etextools-examples.tex % \cmditem{csvtolistadd}{listmacro}{csvlistmacro} \cmdlabel{csvtolistadd}\seeimpl{csvtolistadd} % \cmditem*{csvtolistadd*}{listmacro}{item,item,item...} % -% |\csvtolistadd| acts similarly but does not reset the \prm{listmacro} to |\@empty|: +% |\csvtolistadd| acts similarly but does not reset the \prm{listmacro} to |\@empty|. +% +% +% \subsection{Converting lists of tokens to \sty{etoolbox}-lists} +% +% \cmditem{tokstolist}{listmacro}{tokenslistmacro} \cmdlabel{tokstolist}\seeimpl{tokstolist} +% \cmditem*{tokstolist*}{listmacro}{list of tokens} % +% |\tokstolist| converts a list of tokens (no separator) into an internal \sty{etoolbox} list. +% +% It's also the first application of the \cmdref{toksloop} macro just defined. +% +% \cmditem{tokstolistadd}{listmacro}{tokslistmacro} \cmdlabel{tokstolistadd}\seeimpl{tokstolistadd} +% \cmditem*{tokstolistadd*}{listmacro}{list of tokens} +% +% |\tokstolistadd| acts similarly but does not reset the \prm{listmacro} to |\@empty|. + % % \subsection{Removing elements from \sty{etoolbox}-lists} % @@ -569,32 +659,106 @@ and etextools-examples.tex % Commands |\listgdel| and |\listxdel| are similar, except that the assignment (\ie the redefinition % of the list) is global; for the latter, the \prm{item} is first expanded using |\protected@edef|: % +% \end{ltxsyntax} % % \subsection{Index of an element in a list} % +% \subsubsection{\sty{etoolbox}-lists} +% +% \begin{ltxsyntax} +% +% \cmditem{getlistindex}[myindex]{item}{listmacro} \cmdlabel{getlistindex}\seeimpl{getlistindex} +% \cmditem*{xgetlistindex}[myindex]{item}{listmacro} \cmdlabel{xgetlistindex} +% \cmditem*{getlistindex*}[myindex]{item}{list} +% \cmditem*{xgetlistindex*}[myindex]{item}{list} % -% \cmditem{getlistindex}{item}{listmacro} \cmdlabel{getlistindex}\seeimpl{getlistindex} -% \cmditem*{xgetlistindex}{item}{listmacro} \cmdlabel{xgetlistindex} -% \cmditem*{getlistindex*}{item}{list} -% \cmditem*{xgetlistindex*}{item}{list} +% \end{ltxsyntax} % % Sometimes it is interesting to know at which offset in a list lies a given item. |\getlistindex| answers to this question. -% |\xgetlistindex| does the same thing but expand the \prm{item} (using |\protected@edef|) prior looking for it in the list. -% The result (\ie the position of \prm{item} in \prm{list}) is stored in |\indexinlist|. +% |\xgetlistindex| does the same thing but expands the \prm{item} while looking for it in the list. +% +% The comparison is \textit{catcode agnostic}. +% +% As for the command-list-parser, the star versions are designed in case the list (in the second argument) is already expanded. +% +% When used\pdfFE on pdf\TeX{}, |\pdfstrcmp| does the comparison and the macros are purely expandable: +% % \begin{itemize} -% \item \ If \prm{item} is not found in the \prm{list} then |\indexinlist| is 0 -% \item \ If \prm{item} is found in first position then |\indexinlit| is 1 and so on. +% \item \ If \prm{item} is not found in the list, \cs{getlistindex} expands to 0 +% \item \ If \prm{item} is found in first position then \cs{getlistindex} expands to 1 and so on. % \end{itemize} % +% +% Those macros are purely expandable only if |\pdfstrcmp| exists. +% Otherwise, the comparison is done with \sty{etoolbox}-|\ifstrequal| and you shall use the optional argument +% to let the result in: +% \begin{tabbing} +% \qquad\=|\getlistindex[\myindex]{|\prm{item}|}{|\prm{listmacro}|}| \\ +% \end{tabbing} +% +% \textbf{N.B. If \cs{myindex} is not a counter it is (possibly \textit{re-})defined as macro.} +% +% \subsubsection{Comma-separated lists} +% +% \begin{ltxsyntax} +% \cmditem{getcsvlistindex}[myindex]{item}{csvlistmacro} \cmdlabel{getcsvlistindex}\seeimpl{getcsvlistindex} +% \cmditem*{xgetcsvlistindex}[myindex]{item}{csvlistmacro} \cmdlabel{xgetcsvlistindex} +% \cmditem*{getcsvlistindex*}[myindex]{item}{item,item,item,...} +% \cmditem*{xgetcsvlistindex*}[myindex]{item}{item,item,item,...} +% \end{ltxsyntax} +% +% This is the same as \cmdref{getlistindex} but for comma-separated lists. +% % As for the command-list-parser, the star versions are designed in case the list (in the second argument) is already expanded. % +% Those macros\pdfFE are purely expandable only if |\pdfstrcmp| exists. +% +% Otherwise, use the optional argument to let the result in: +% \begin{tabbing} +% \qquad\=|\getcsvlistindex*[\myindex]{|\prm{item}|}{|\prm{item,item,item...}|}| \\ +% \end{tabbing} +% +% If \cs{myindex} is not a counter it is (possibly \textit{re-})defined as macro. +% +% \subsubsection{Lists of tokens} +% +% \begin{ltxsyntax} +% \cmditem{gettokslistindex}[myindex]{item}{tokenslistmacro} \cmdlabel{gettokslistindex}\seeimpl{gettokslistindex} +% \cmditem*{gettokslistindex*}[myindex]{item}{list of tokens} +% \end{ltxsyntax} +% +% There\FE is no x- version for those macros. They work in a different way: the comparison if done by \cs{ifx} and +% not \cmd{pdfstrcmp}. +% +% Therefore, \cs{gettokslistindex} is \textbf{always purely expandable}, but for symmetry reasons, the optional form:§ +% \begin{tabbing} +% \qquad\=|\gettokslistindex[\myindex]{|\prm{item}|}{|\prm{tokenslistmacro}|}| \\ +% and:\> |\gettokslistindex*[\myindex]{|\prm{item}|}{|\prm{list of tokens}|}| +% \end{tabbing} +% are defined. +% +% An interesting application is the following: +% +% \begin{Verbatim}[gobble=1,commandchars=!\[\]] +% !textbf[\ifcase \gettokslistindex*{R}{LORG}] +% Not in the list: Error ?% +% \or Here it's L% +% \or Here it's O% +% \or Here it's R% +% \or Here it's G% +% !textbf[\fi] +% \end{Verbatim} +% +% Please, refer to the examples... % % \subsection{Extract by index from a list} % % \begin{ltxsyntax} % -% \cmditem{getlistitem}{listmacro}{index [numexpr expression]} \cmdlabel{getlistitem}\seeimpl{getlistitem} -% \cmditem*{getlistitem*}{list}{index [numexpr expression]} +% \subsubsection{\sty{etoolbox}-lists} +% +% \cmditem{getlistitem}{index [numexpr expression]}{listmacro} \cmdlabel{getlistitem}\seeimpl{getlistitem} +% \cmditem*{getlistitem*}{index [numexpr expression]}{list} % % Now\FE the reverse operation of ``getting the index'' is ``getting the element'' whose index is known. Note that this macro % is fully expandable for we don't have to compare the items (just count the loop using |\numexpr| -- no counter). Therefore we use the @@ -604,8 +768,71 @@ and etextools-examples.tex % \item \ If the \prm{index} is non positive or $>n$ then the macro expands to nothing (|{}|). % \end{itemize} % +% \subsubsection{Comma-separated lists} +% +% \cmditem{getcsvlistitem}{index [numexpr expression]}{csvlistmacro} \cmdlabel{getcsvlistitem}\seeimpl{getcsvlistitem} +% \cmditem*{getcsvlistitem*}{index [numexpr expression]}{item,item,item,...} +% +% This is\FE the same as \cmdref{getlistitem} but for comma-separated lists. +% +% \subsubsection{Lists of tokens} +% +% \cmditem{gettokslistitem}{index [numexpr expression]}{tokenslistmacro} \cmdlabel{gettokslistitem}\seeimpl{gettokslistitem} +% \cmditem*{gettokslistitem*}{index [numexpr expression]}{list of tokens} +% +% The same\FE as \cmdref{getlistitem} for list of tokens. % \end{ltxsyntax} % +% \section{Vectorized \cmd{futurelet}} +% +% +% \sty{etextools} defines a vectorized version of \cs{futurelet}. The idea is to say: +% +% \quad|\collecttoks\macro{|\prm{list of allowed tokens}|}{|\prm{commands to execute next}|}| +% +% Then \cs{collecttoks} is a kind of simple scanner for tokens. It can be used to define an \textbf{\textit{undelimited macro}} +% \ie a macro that has no delimiter but whose content of arguments is restricted. +% +% \begin{ltxsyntax} +% \cmditem{collecttoks}{cs-token}{list of tokens}{commands to expand after} \cmdlabel{collecttoks}\seeimpl{collecttoks} +% \end{ltxsyntax} +% +% The macro \cs{collecttoks} will read the following tokens with \cs{futurelet}. If that token is in the allowed +% list, then it will append it to \cs{macro} (\prm{cs-token}) and continue, scanning the tokens one after another. +% +% Until it founds a token which is not in the list. Then it stops reading and execute the \prm{commands to expand}. +% Those commands may use the \cs{macro} defined for analyse or whatever the user want. +% +% \medskip +% As an application, it can be used to define an easy interface for |\hdashline| (the dashed lines in tabulars and arrays +% provided by the \sty{arydshln} package): modifying \cmd{hline} in order to give sense to the following: +% \begin{tabbing} +% \qquad\=|\hline..|\qquad\=|\hline--|\qquad\=|\hline==|\qquad\= |\hline.-|\qquad\=|\hline.-.|\ \= etc. +% \end{tabbing} +% +% After having collected the allowed tokens with:§ +% |\collecttoks\nexttokens{.-=}{|\prm{commands next}|}| \quad it is possible to +% test the pattern given using \cs{pdfstrcmp} and, for example, the \CSbf{switch} construction of the \sty{boolexpr} package: +% +% \begin{Verbatim}[gobble=1,commandchars=!()] +% !textbf(\switch[\pdfstrcmp{\nexttokens}]) +% \case{{..}}\hdashline[parameters]% +% \case{{--}}\hdashline[parameters]% +% \case{{==}}\hdashline[parameters]% +% \case{[.-.}}\hdashline[parameters]% +% \otherwise \original@hline% +% !textbf(\endswitch) +% \end{Verbatim} +% +% \CSbf{switch} is purely expandable. +% +% If you replace \cs{pdfstrcmp} by |\ifstrequal|, \cs{switch} works but is not purely expandable. +% +% See \sty{boolexpr} (\CTAN{macros/latex/contrib/boolexpr/}) for more information on \cs{switch}. +% +% +% +% % \StopEventually{ % } % @@ -620,7 +847,7 @@ and etextools-examples.tex %<*package> \NeedsTeXFormat{LaTeX2e}[1996/12/01] \ProvidesPackage{etextools} - [2009/07/14 v2e e-TeX more useful tools for LaTeX package writers] + [2009/08/14 v2h e-TeX more useful tools for LaTeX package writers] \csname ettl@onlyonce\endcsname\let\ettl@onlyonce\endinput % \end{macrocode} % @@ -636,10 +863,22 @@ and etextools-examples.tex % Furthermore, the space token must have its natural catcode (10) all along this package. % % \begin{macrocode} -\edef\ettl@restore@space@catcode{\catcode`\ =\the\catcode`\ } -\AtEndOfPackage{\ettl@restore@space@catcode - \let\ettl@restore@space@catcode\ettl@undefined} -\catcode`\ =10 +\let\ettl@AtEnd\@empty +\def\TMP@EnsureCode#1#2{% + \edef\ettl@AtEnd{% + \ettl@AtEnd + \catcode#1 \the\catcode#1\relax + }% + \catcode#1 #2\relax +} +\TMP@EnsureCode{32}{10}% space +\ifundef\pdfstrcmp{% + \TMP@EnsureCode{33}{9}% ! ignore + \TMP@EnsureCode{34}{14}% " comment +}{\TMP@EnsureCode{33}{14}% ! comment + \TMP@EnsureCode{34}{9}% " ignore +} +\AtEndOfPackage{\ettl@AtEnd\undef\ettl@AtEnd} % \end{macrocode} % % \subsection{A few (7) ``helper'' macros} @@ -653,21 +892,21 @@ and etextools-examples.tex \long\def\ettl@afterfi#1\fi{\fi#1} \long\def\ettl@afterfifi#1\fi\fi{\fi\fi#1} \long\def\ettl@afterelsefi#1\else#2\fi\fi{\fi#1} +\long\def\ettl@afterorfi#1\or#2\fi{\fi#1} % \end{macrocode} % -% \begin{macro}{\ettl@cdr} -% {\rmk \cmd{ettl@cdr} is only used in \cmdref{ifsinglechar}} -% \begin{macrocode} -\begingroup\catcode`\|=4 -\long\gdef\ettl@cdr#1#2|{#2} -\endgroup -% \end{macrocode} -% \end{macro} -% % \iffalse %<package> % \fi % +% \begin{macro}{\ettl@ifstrcmp} +% Use of the pdf\TeX{} primitive \cs{pdfstrcmp} and design a \LaTeX{} form. +% \begin{macrocode} +\def\ettl@ifstrcmp#1#2{\csname @% + \ifnum\pdfstrcmp{#1}{#2}=0 first\else second\fi oftwo\endcsname} +% \end{macrocode} +% \end{macro} +% % \begin{macro}{\@gobblescape} % % This sequence of command is very often used, even in \sty{latex.ltx}. So @@ -680,20 +919,13 @@ and etextools-examples.tex % \end{macro} % % -% \begin{macro}{\str@gobblescape} -% -% With \eTeX{} |\detokenize| it is now possible to invoke a |\string| on an arbitrary -% sequence of tokens. Unfortunately, |\detokenize| adds a -% space tokens at the very end of the sequence. |\str@gobblescape| acts exactly -% the same way as |\@gobblescape| \ie it removes the first character from a string, but removes -% the trailing spaces as well: -% % \begin{macrocode} -\newcommand\str@gobblescape[1]{\expandafter\deblank\expandafter{% - \expandafter\@gobble\detokenize{#1}}} +\def\ettl@onlypdfTeX#1#2{\ifundef{#1} + {\def#2{\PackageError{etextools}{\string#1\space primitive not found\MessageBreak + pdfTeX seems not to be running} + {\string#2\space works only if used with pdfTeX (requires \string#1)}}} + {}} % \end{macrocode} -% \end{macro} -% % % \subsection{Expansion control} % @@ -748,39 +980,67 @@ and etextools-examples.tex % \fi % % -% \subsection{String manipulation} +% \subsection{Character and Strings} % -% \begin{macro}{\deblank} \cmdlabel{impl:deblank} +% \iffalse +%<package> +%<package>% \ifempty{ text }{ true }{ false } +% \fi % -% Note that the leading spaces \seedesc{deblank}are automatically removed by \TeX's mastication mechanism. +% \begin{macro}{\ifempty} \cmdlabel{impl:ifempty} +% |\ifempty| is based on |\detokenize| and can manage with any argument.\seedesc{ifempty} +% \begin{macrocode} +\newcommand\ifempty[1]{\csname @\expandafter\ifx + \expandafter\relax\detokenize{#1}\relax + first\else second\fi oftwo\endcsname} +% \end{macrocode} +% \end{macro} +% +% \iffalse +%<package> +%<package>% \ifnotempty{ text }{ true }{ false } +% \fi % +% \begin{macro}{\ifnotempty} \cmdlabel{impl:ifnotempty} +% |\ifnotempty| is based on |\detokenize| and can manage with any argument.\seedesc{ifnotempty} % \begin{macrocode} -\newcommand\deblank{} -\newcommand\ifempty{} -\begingroup\catcode`\|=4% a | as a tab array -\long\gdef\deblank#1{\@deblank#1 |} -\long\gdef\@deblank#1 #2|{\ifblank{#2}{#1}{#1\@deblank#2 |}} +\newcommand\ifnotempty[1]{\csname @\expandafter\ifx + \expandafter\relax\detokenize{#1}\relax + second\else first\fi oftwo\endcsname} % \end{macrocode} % \end{macro} % % \iffalse %<package> -%<package>% \ifempty{ text }{ true }{ false } +%<package>% \xifempty{ text }{ true }{ false } % \fi -% \begin{macro}{\ifempty} \cmdlabel{impl:ifempty} -% |\ifempty| is amazing because the code is so concise!\seedesc{ifempty} +% \begin{macro}{\xifempty} \cmdlabel{impl:xifempty} +% |\xifempty| is based on pdf-TeX{} |\pdfstrcmp| and work with any argument.\seedesc{xifempty} % \begin{macrocode} -\long\gdef\ifempty#1{\csname @\ifx|#1|first\else second\fi oftwo\endcsname} -\endgroup% catcode group +\newcommand\xifempty[1]{\xifstrcmp{#1}{}} +\ettl@onlypdfTeX\pdfstrcmp\xifempty % \end{macrocode} % \end{macro} +% % \iffalse %<package> +%<package>% \ifnotblank{ text }{ true }{ false } % \fi % -% \goodbreak +% \begin{macro}{\ifnotblank} \cmdlabel{impl:ifnotblank} +% |\ifnotblank| reverses the test of |\ifblank|.\seedesc{ifnotblank} +% \begin{macrocode} +\begingroup\catcode`\&=3\catcode`\:=12 +\ifcsundef{ifnotblank}{% +\long\gdef\ifnotblank#1{\etb@ifblank@i#1&&\@firstoftwo\@secondoftwo:}} +\relax\endgroup +% \end{macrocode} +% \end{macro} % -% \subsection{Expanded string comparison} +% \iffalse +%<package> +%<package>% \xifblank{ string }{ true }{ false } +% \fi % % \begin{macro}{\xifblank}\cmdlabel{impl:xifblank} % Just expands the parameter using |\protected@edef| before testing for |\ifblank|: \seedesc{xifblank} @@ -792,61 +1052,135 @@ and etextools-examples.tex % \end{macrocode} % \end{macro} % -% \begin{macro}{\xifstrequal}\cmdlabel{impl:xifstrequal} -% Same idea: protected expansion before testing: \seedesc{xifstrequal} -% \begin{macrocode} -\newrobustcmd\xifstrequal[2]{% - \begingroup\protected@edef\@tempa{#1}\protected@edef\@tempb{#2}% - \ifx\@tempa\@tempb \aftergroup\@firstoftwo - \else \aftergroup\@secondoftwo - \fi\endgroup} -% \end{macrocode} -% \end{macro} +% +% \iffalse +%<package> +%<package>% \iffirstchar{ string1 }{ string2 }{ true }{ false } +% \fi % % \begin{macro}{\iffirstchar}\cmdlabel{impl:iffirstchar} % |\iffirstchar| test if |#1| and |#2| begins with the same character. \seedesc{iffirstchar} % \begin{macrocode} -\newcommand\iffirstchar[2]{% - \if \expandafter\@car\string#2\relax\@nil\expandafter\@car#1\string\\\@nil - \ettl@afterelse\ifblank{#2}\@secondoftwo\@firstoftwo - \else \expandafter\@secondoftwo - \fi} +\newcommand\iffirstchar[2]{\csname @% + \if \expandafter\@car\detokenize{#2}\relax\@nil\expandafter\@car\detokenize{#1}\string\\\@nil + \ifblank{#2}{second}{first}% + \else second% + \fi oftwo\endcsname} % \end{macrocode} % \end{macro} % +% \iffalse +%<package> +%<package>% \ifsinglechar character{ string }{ true }{ false } +% \fi +% % \begin{macro}{\ifsinglechar}\cmdlabel{impl:ifsinglechar} % Test if |#2| is a single character equal to |#1|: \seedesc{ifsinglechar} % \begin{macrocode} -\newcommand\ifsinglechar{} -\begingroup\catcode`\|=4 -\long\gdef\ifsinglechar#1#2{% +\newcommand\ifsinglechar[2]{% % \end{macrocode} % % \begin{codecomment} % Remember that neither \prm{string1} nor \prm{string2} is expanded.§ % First: test if |#2| is a single character: % \begin{macrocode} - \csname @\expandafter\expandafter\expandafter\ifx - \expandafter\expandafter\expandafter|% - \expandafter\ettl@cdr\string#2||first\else second\fi - oftwo\endcsname + \csname @\ifblank{#2}{second}{% +" \ifnum\pdfstrcmp{\detokenize{#1}}{\detokenize{#2}}=0 +" \ifnum\pdfstrcmp{\detokenize{#2}}{\expandafter\@car\detokenize{#2}\relax\@nil}=0 +" first% +" \else second% +" \fi +" \else second% +" \fi oftwo\endcsname}} +! \expandafter\expandafter\expandafter\ifx +! \expandafter\expandafter\expandafter\relax\expandafter\@cdr\detokenize{#2}\@nil\relax +! \iffirstchar{#1}{#2}{first}{second}\else second\fi oftwo\endcsname}} % \end{macrocode} -% The test returned \prm{true}: therefore test further the character codes of |#2| and |#1|, and -% switch to \prm{true} only in case of equality: +% \end{codecomment} +% \end{macro} +% +% \iffalse +%<package> +%<package>% \iflastchar{ string1 }{ string2 }{ true }{ false } +% \fi +% +% \begin{macro}{\iflastchar} \cmdlabel{impl:iflastchar} +% This macro is not purely expandable. \seedesc{iflastchar} % \begin{macrocode} - {\iffirstchar{#1}{#2}} +\begingroup\catcode`\&=3 +\long\gdef\iflastchar#1#2{% + \long\def\ettl@iflastchar##1#1##2&{% + \ifstrcmp{##2}{#1}\@firstoftwo{% + \ifempty{##2}\@secondoftwo{\ettl@iflastchar##2&}} + }\ettl@iflastchar#2#1&} +\endgroup % \end{macrocode} -% Otherwise, switch to \prm{false} +% \end{macro} +% +% +% \iffalse +%<package> +%<package>% \ifstrcmp{ string1 }{ string2 }{ true }{ false } +% \fi +% +% \begin{macro}{\ifstrcmp}\cmdlabel{impl:ifstrcmp} +% The macro is base on the |\pdfstrcmp| primitive.\seedesc{ifstrcmp} % \begin{macrocode} - \@secondoftwo} -\endgroup% catcode group +\newcommand\ifstrcmp[2]{\csname @% + \ifnum\pdfstrcmp{\detokenize{#1}}{\detokenize{#2}}=0 first\else second\fi + oftwo\endcsname} +\ettl@onlypdfTeX\pdfstrcmp\ifstrcmp +% \end{macrocode} +% \end{macro} +% +% \iffalse +%<package> +%<package>% \xifstrcmp{ string1 }{ string2 }{ true }{ false } +% \fi +% +% \begin{macro}{\xifstrcmp}\cmdlabel{impl:xifstrcmp} +% The macro is based on the |\pdfstrcmp| primitive.\seedesc{ifxstrcmp} +% \begin{macrocode} +\newcommand\xifstrcmp[2]{\csname @% + \ifnum\pdfstrcmp{#1}{#2}=0 first\else second\fi + oftwo\endcsname} +\ettl@onlypdfTeX\pdfstrcmp\ifxstrcmp % \end{macrocode} -% \end{codecomment} % \end{macro} % +% \begin{macro}{\xifstrequal}\cmdlabel{impl:xifstrequal} +% The macro is based on \sty{etoolbox}-|\ifstrequal|.\seedesc{ifxstrequal} +% \begin{macrocode} +\newrobustcmd*\xifstrequal[2]{\begingroup + \protected@edef\@xifstrequal{\endgroup\noexpand\ifstrequal{#1}{#2}% + }\@xifstrequal} +% \end{macrocode} +% \end{macro} +% +% +% % \iffalse %<package> -%<package>%\FE@testopt{#1}{commands}{default option} +%<package>% \ifstrmatch{ pattern }{ true }{ false } +% \fi +% +% \begin{macro}{\ifstrmatch}\cmdlabel{impl:ifstrmatch} +% The macro is base on the |\pdfmatch| primitive.\seedesc{ifstrmatch} +% \begin{macrocode} +\newcommand\ifstrmatch[2]{\csname @% + \ifnum\pdfmatch{\detokenize{#1}}{\detokenize{#2}}=1 first\else second\fi + oftwo\endcsname} +\ettl@onlypdfTeX\pdfmatch\ifstrmatch +% \end{macrocode} +% \end{macro} +% +% +% \subsection{Purely expandable macros with options} +% +% \iffalse +%<package>%---------------------------------------------------------------------------- +%<package>% Purely Expandable Macros With Options / Star Forms / Variants +%<package>% \FE@testopt{ #1 }{ commands }{ default option } % \fi % \begin{macro}{\FE@testopt}\cmdlabel{impl:FE@testopt} % Fully expandable |\@testopt|-like test:\seedesc{FE@testopt} @@ -858,7 +1192,7 @@ and etextools-examples.tex % % \iffalse %<package> -%<package>%\FE@ifstar{#1}{\StarredMacro}{\NotStarredMacro} +%<package>% \FE@ifstar{ #1 } { \StarredMacro }{ \NotStarredMacro } % \fi % \begin{macro}{\FE@ifstar}\cmdlabel{impl:FE@ifstar} % Fully expandable |\@ifstar|-like test:\seedesc{FE@ifstar} @@ -867,6 +1201,19 @@ and etextools-examples.tex % \end{macrocode} % % \end{macro} +% +% \iffalse +%<package> +%<package>% \FE@ifchar{#1}{#2}{ \SpecialFormMacro }{ \NormalMacro } +% \fi +% \begin{macro}{\FE@ifchar}\cmdlabel{impl:FE@ifchar} +% Plus généralement, on peut tester si une macro est suivie d'un caractère donné:\seedesc{FE@ifchar} +% \begin{macrocode} +\newcommand\FE@ifchar[4]{\ifsinglechar{#1}{#2}{#3}{#4{#2}}} +% \end{macrocode} +% \end{macro} +% +% % \iffalse %<package> % \fi @@ -910,27 +1257,23 @@ and etextools-examples.tex % This is possible because the list-parser has always a mandatory argument (the \prm{list} itself or the \prm{listmacro}) : % \begin{macrocode} \long\def#1####1{\noexpand\FE@ifstar{####1} - {\`ettl@lst@star\string#1`} - {\`ettl@lst@nost\string#1`}}% + {\`ettl@lst@opt\string#1`{}} + {\`ettl@lst@opt\string#1`\noexpandafter}}% % \end{macrocode} % Both starred and not-starred versions have an optional argument which is the auxiliary command, whose name is |\do| if not specified. % It is possible to test the option for the same reason: % \begin{macrocode} - \long\csdef{ettl@lst@star\string#1}####1{\noexpand\FE@testopt{####1} - {\`ettl@lst@star@pt\string#1`}{\noexpand\do}}% - \long\csdef{ettl@lst@nost\string#1}####1{\noexpand\FE@testopt{####1} - {\`ettl@lst@nost@pt\string#1`}{\noexpand\do}}% + \long\csdef{ettl@lst@opt\string#1}####1####2{\noexpand\FE@testopt{####2} + {\`ettl@lst@@pt\string#1`{####1}}{\noexpand\do}}% % \end{macrocode} % Definition of the parser with its arguments :\quad |[optional command]{list or listmacro}|. If the starred version % was used, then we do not have to expand the (mandatory) \prm{list}: % \begin{macrocode} - \long\csdef{ettl@lst@star@pt\string#1}[####1]####2{% - \`ettl@lst\string#1`{####2}{####1}}% + \long\csdef{ettl@lst@@pt\string#1}####1[####2]####3{% + ####1\`ettl@lst\string#1`####1{####3}{####2}}% % \end{macrocode} % On the other hand, if the parser was not starred, the (mandatory) \prm{listmacro} is expanded once: % \begin{macrocode} - \long\csdef{ettl@lst@nost@pt\string#1}[####1]####2{% - \noexpandafter\`ettl@lst\string#1`\noexpandafter{####2}{####1}}% % \end{macrocode} % ListParser is defined and leads to |\`ettl@lst\string\ListParser`| in all cases; here the \prm{list} is in first position, % the auxiliary commands come after, so we reverse the order and add a \prm{separator} in case the \prm{list} is empty: @@ -993,38 +1336,71 @@ and etextools-examples.tex % \end{macrocode} % \end{codecomment} % +% \begin{codecomment} +% Definition of |\toksloop| (with no delimiter): +% \begin{macrocode} +\DeclareCmdListParser\toksloop{}% +% \end{macrocode} +% \end{codecomment} % % \iffalse %<package> -%<package>%\csvtolist\csvListMacro -%<package>%\csvtolist*{item,item,item} +%<package>% \csvtolist \ListMacro \csvListMacro +%<package>% \csvtolist* \ListMacro {item,item,item} % \fi % \begin{macro}{\csvtolist}\cmdlabel{impl:csvtolist} % This is the first application of |\csvloop|:\seedesc{csvtolist} % \begin{macrocode} -\newcommand\csvtolist{\@ifstar\star@csvtolist\nost@csvtolist}% -\def\star@csvtolist#1{\let#1\@empty\csvloop*[{\unexpanded{\listadd#1}}]}% -\def\nost@csvtolist#1{\let#1\@empty\csvloop[{\unexpanded{\listadd#1}}]}% +\newrobustcmd*\csvtolist{\@ifstar + {\ettl@tolist\z@{}\csvloop} + {\ettl@tolist\z@\expandnext\csvloop}}% +\long\def\ettl@tolist#1#2#3#4#5{\ifx#1\z@\let#4\@empty\fi + \def\ettl@to@list{#3*[{\unexpanded{\listadd#4}}]% + }#2\ettl@to@list{#5}} % \end{macrocode} % \end{macro} % % \iffalse %<package> -%<package>%\csvtolistadd\csvListMacro -%<package>%\csvtolistadd*{item,item,item} +% \fi +% +% \begin{macro}{\tokstolist}\cmdlabel{impl:tokstolist} +% This is the first application of |\toksloop|:\seedesc{tokstolist} +% \begin{macrocode} +\newrobustcmd*\tokstolist{\@ifstar{\ettl@tokstolist\z@{}}{\ettl@tokstolist\z@\expandnext}} +\def\ettl@tokstolist#1#2#3#4{\ifx#1\z@\let#3\@empty\fi + \def\ettl@toks@tolist{\toksloop*[{\unexpanded{\listadd#3}}]}% + #2\ettl@toks@tolist{#4{}}} +% \end{macrocode} +% \end{macro} +% +% +% \iffalse +%<package> +%<package>% \csvtolistadd \ListMacro \csvListMacro +%<package>% \csvtolistadd* \ListMacro {item,item,item} % \fi % \begin{macro}{\csvtolistadd}\cmdlabel{impl:csvtolistadd} % It's quite the same\seedesc{csvtolistadd} as the latter except it does not % reset the list to empty at the very beginning: % \begin{macrocode} -\newcommand\csvtolistadd{\@ifstar\star@csvtolistadd\nost@csvtolistadd}% -\def\star@csvtolistadd#1#2{\ifblank{#2} - {\let#1\@empty}{\csvloop*[{\unexpanded{\listadd#1}}]{#2}}}% -\def\nost@csvtolistadd#1#2{\ifblank{#2} - {\let#1\@empty}{\csvloop[{\unexpanded{\listadd#1}}]{#2}}}% +\newrobustcmd*\csvtolistadd{\@ifstar + {\ettl@tolist\@ne{}\csvloop} + {\ettl@tolist\@ne\expandnext\csvloop}} % \end{macrocode} % \end{macro} % +% \iffalse +%<package> +% \fi +% +% \begin{macro}{\tokstolistadd}\cmdlabel{impl:tokstolistadd} +% It's quite the same\seedesc{tokstolistadd} as the latter except it does not +% reset the list to empty at the very beginning: +% \begin{macrocode} +\newrobustcmd*\tokstolistadd{\@ifstar{\ettl@tokstolist\@ne{}}{\ettl@tokstolist\@ne\expandnext}}% +% \end{macrocode} +% \end{macro} % % \iffalse %<package> @@ -1068,7 +1444,7 @@ and etextools-examples.tex % In order to preserve the hash-table from temporary definitions, a group is opened: % \begin{macrocode} \begingroup - \def\@tempa##1|#3|##2&{##1|##2\@tempb}% + \long\def\@tempa##1|#3|##2&{##1|##2\@tempb}% % \end{macrocode} % % |\@tempa| is a delimited macro whose aim is to remove the first \prm{item} found in the list @@ -1079,7 +1455,7 @@ and etextools-examples.tex % The result of |\@tempa| expansion is then given to |\@tempb| whose purpose is to cancel out % whatever is found between the two delimiters: \textbar|\@tempb|...\textbar|\@tempb|: % \begin{macrocode} - \def\@tempb|##1|\@tempb##2|\@tempb{% + \long\def\@tempb|##1|\@tempb##2|\@tempb{% \ifblank{##2}{\unexpanded{##1}} % \end{macrocode} % If the \prm{item} \textbf{was not} is the list, then |##2| will be empty, and§ @@ -1096,7 +1472,7 @@ and etextools-examples.tex % the expansion of |\@tempa|. The macro |\@tempx| itself has an argument: it is (at first stage) the % replacement text of \prm{listmacro}: % \begin{macrocode} - \def\@tempx##1&{\expandafter\@tempb\@tempa|##1|\@tempb|#3|&}% + \long\def\@tempx##1&{\expandafter\@tempb\@tempa|##1|\@tempb|#3|&}% \edef\@redef{\endgroup \unexpanded{#1#2}{% ie: \def or \gdef \listmacro % \end{macrocode} @@ -1118,7 +1494,8 @@ and etextools-examples.tex %\iffalse %<package> %<package> -%<package>% \getlistindex (result in \indexinlist) +%<package>% \getlistindex[\indexmacro]{ \listmacro } +%<package>% \getlistindex*[\indexmacro]{ expanded list } % \fi % % @@ -1129,63 +1506,264 @@ and etextools-examples.tex % % We first need to get into a group where delimiter `\,\textbar\,' and `\,\&\,' have catcode 3: % \begin{macrocode} +\newcommand\getlistindex[1]{\FE@ifstar{#1} + {\ettl@getlistindex{}\unexpanded} + {\ettl@getlistindex\expandnext\unexpanded}} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\xgetlistindex}\cmdlabel{impl:xgetlistindex} +% |\xgetlistindex| is similar but the \prm{item} is expanded during string comparison (inside |\pdfstrcmp| is pdf\TeX{}, +% or before the test if this primitive is not found). +% \begin{macrocode} +\newcommand\xgetlistindex[1]{\FE@ifstar{#1} + {\ettl@getlistindex{}\@firstofone} + {\ettl@getlistindex\expandnext\@firstofone}} +% \end{macrocode} +% \end{macro} +% +% +% Then the following macro does the job in a loop, which is fully expandable when we can use |\pdfstrcmp|: +% +% \begin{macrocode} \begingroup\catcode`\|=3\catcode`\&=3 -\gdef\getlistindex#1{\FE@ifstar{#1}{\ettl@getlistindex{}} - {\ettl@getlistindex\expandnext}} -% \@ifstar{\ettl@getlistindex{}}{\ettl@getlistindex{\expandnext}}} +\long\gdef\ettl@getlistindex#1#2#3{\FE@testopt{#3}{\ettl@get@listindex{#1}{#2}}{}} +\long\gdef\ettl@get@listindex#1#2[#3]#4#5{#1\ettl@get@list@idx{#5}{#4}{\numexpr1}{#2}[{#3}]} +\long\gdef\ettl@get@list@idx#1#2#3#4[#5]{% #1=expanded list, #2=item, #3=index, #4=\unexpanded (event., #5=indexmacro) + \ifblank{#1}0% the (remainder of) the list is empty +" {\xifstrcmp{\expandonce{\ettl@list@first@item#1&}}{#4{#2}}} +! {\ettl@listitem@cmp{\ettl@list@first@item#1&}{#2}{#4}} + {\ifblank{#5}{\number#3\relax}{\ettl@ifiscount{#5}{#5=\number#3\relax}{\edef#5{\number#3}}}} + {\expandnext\ettl@get@list@idx{\ettl@list@other@item#1&}{#2}{#3+1}{#4}[{#5}]}} +% \end{macrocode} +% +% \begin{codecomment} +% +% The next two macros expand to the first item in a list or the remainder of the list respectively: +% +% \begin{macrocode} +\long\gdef\ettl@list@first@item#1|#2&{#1} +\long\gdef\ettl@list@other@item#1|#2&{#2} +!\long\gdef\ettl@listitem@cmp#1#2#3{% +! \ifx#3\unexpanded\def\ettl@listitem@cmp@{#2}% +! \else\protected@edef\ettl@listitem@cmp@{#2}% +! \fi +! \expandafter\ifstrequal\expandafter{#1}{#2}} +\edef\ettl@ifiscount{% + \gdef\noexpand\ettl@ifiscount##1{% + \noexpand\expandafter\noexpand\ettl@ifiscount@i + \noexpand\meaning##1\string\count\noexpand\@nil}% +}\ettl@ifiscount +\edef\ettl@ifiscount@i{% + \gdef\noexpand\ettl@ifiscount@i##1\string\count##2\noexpand\@nil{% + \noexpand\ifempty{##1}}% +}\ettl@ifiscount@i +% \end{macrocode} +% +% \end{codecomment} +% +% \iffalse +%<package> +%<package>%\getcsvlistindex{ item }{ csvlistmacro } +%<package>%\getcsvlistindex*{ item }{ item,item,item } +% \fi +% \begin{macro}{\getcsvlistindex} \cmdlabel{impl:getcsvlistindex} +% \strut\seedesc{getcsvlistindex} +% \begin{macrocode} +\long\gdef\getcsvlistindex#1{\FE@ifstar{#1} + {\ettl@getcsvlistindex{}\unexpanded} + {\ettl@getcsvlistindex\expandnext\unexpanded}} % \end{macrocode} % \end{macro} % -% |\xgetlistindex| is similar with prior expansion of \prm{item}: +% |\xgetcsvlistindex| is similar but the \prm{item} is expanded during string comparison (inside |\pdfstrcmp| is pdf\TeX{}, +% or before the test if this primitive is not found). +% % \begin{macrocode} -\gdef\xgetlistindex#1{\FE@ifstar{#1}{\ettl@xgetlistindex{}} - {\ettl@xgetlistindex\expandnext}} -\gdef\ettl@xgetlistindex#1#2#3{\begingroup - \protected@edef\next{\endgroup\unexpanded{\ettl@getlistindex{#1}{#2}}{#3}% - }\next} +\long\gdef\xgetcsvlistindex#1{\FE@ifstar{#1} + {\ettl@getcsvlistindex{}\@firstofone} + {\ettl@getcsvlistindex\expandnext\@firstofone}} % \end{macrocode} % -% Then the following macro does the job in a loop, which is not fully expandable because the use of |\ifstrequal|: +% Then the following macro does the job in a loop, which is fully expandable when we can use |\pdfstrcmp|: % % \begin{macrocode} -\gdef\ettl@getlistindex#1#2#3{\begingroup#1\ettl@get@list@idx{#3}{#2}{\numexpr1}} -\gdef\ettl@get@list@idx#1#2#3{% #1=expanded list, #2=item, #3=index +\long\gdef\ettl@getcsvlistindex#1#2#3{\FE@testopt{#3}{\ettl@get@csvlistindex{#1}{#2}}{}} +\long\gdef\ettl@get@csvlistindex#1#2[#3]#4#5{#1\ettl@get@csvlist@idx{#5}{#4}{\numexpr1}{#2}[{#3}]} +\long\gdef\ettl@get@csvlist@idx#1#2#3#4[#5]{% #1=expanded list, #2=item, #3=index, #4=\unexpanded (event., #5=indexmacro) \ifblank{#1}0% the (remainder of) the list is empty - {\expandnext\ifstrequal{\ettl@list@first@item#1&}{#2} - {\endgroup\edef\indexinlist{\number#3\relax}} - {\expandnext\ettl@get@list@idx{\ettl@list@other@item#1&}{#2}{#3+1}}}} +" {\xifstrcmp{\expandonce{\ettl@csvlist@first@item#1&}}{#4{#2}}} +! {\ettl@listitem@cmp{\ettl@csvlist@first@item#1&}{#2}{#4}} + {\ifblank{#5}{\number#3\relax}{\ettl@ifiscount{#5}{#5=\number#3\relax}{\edef#5{\number#3}}}} + {\expandnext\ettl@get@csvlist@idx{\ettl@csvlist@other@item#1&}{#2}{#3+1}{#4}[{#5}]}} % \end{macrocode} % % \begin{codecomment} -% The next two macros expand to the first item in a list or the remainder of the list respectively : +% The next two macros expand to the first item in a list or the remainder of the list respectively: % \begin{macrocode} -\gdef\ettl@list@first@item#1|#2&{#1} -\gdef\ettl@list@other@item#1|#2&{#2} +\long\gdef\ettl@csvlist@first@item#1,#2&{#1} +\long\gdef\ettl@csvlist@other@item#1,#2&{#2} +% \end{macrocode} +% \end{codecomment} +% +% +% \iffalse +%<package> +%<package>%\gettokslistindex{ item }{ tokenslistmacro } +%<package>%\gettokslistindex*{ item }{ list of tokens } +% \fi +% \begin{macro}{\gettokslistindex}\cmdlabel{impl:gettokslistindex} +% \strut\seedesc{gettokslistindex} +% \begin{macrocode} +\long\gdef\gettokslistindex#1{\FE@ifstar{#1} + {\ettl@gettokslistindex{}} + {\ettl@gettokslistindex\expandnext}} +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +\long\gdef\ettl@gettokslistindex#1#2{\FE@testopt{#2}{\ettl@get@tokslistindex{#1}}{}} +\long\gdef\ettl@get@tokslistindex#1[#2]#3#4{#1\ettl@get@tokslist@idx{#4}{#3}{\numexpr1}[{#2}]} +\long\gdef\ettl@get@tokslist@idx#1#2#3[#4]{% #1=expanded list, #2=item, #3=index + \ifblank{#1}0% the (remainder of) the list is empty + {\expandafter\ifx\expandafter#2\ettl@tokslist@first@item#1&% + \ettl@afterelse\ifblank{#4}{\number#3\relax} + {\ettl@ifiscount{#4}{#4=\number#3\relax}{\edef#4{\number#3}}}% + \else \ettl@afterfi + \expandnext\ettl@get@tokslist@idx{\ettl@tokslist@other@item#1&}{#2}{#3+1}[{#4}]% + \fi}} +% \end{macrocode} +% +% \begin{codecomment} +% The next two macros expand to the first item in a list or the remainder of the list respectively: +% \begin{macrocode} +\long\gdef\ettl@tokslist@first@item#1#2&{#1} +\long\gdef\ettl@tokslist@other@item#1#2&{#2} \endgroup% catcode group % \end{macrocode} % \end{codecomment} % % +% +% \iffalse +%<package> +%<package> +%<package>%\getlistitem{ number }{ listmacro } +%<package>%\getlistitem*{ number }{ listmacro } +% \fi % \begin{macro}{\getlistitem}\cmdlabel{impl:getlistitem} % \strut\seedesc{getlistitem} % \begin{macrocode} -\newcommand\getlistitem[1]{\FE@ifstar{#1}\ettl@getlistitem - {\expandnext\ettl@getlistitem}} +\newcommand\getlistitem[1]{\FE@ifstar{#1}{\ettl@getlistitem{}} + {\ettl@getlistitem\expandnext}} \begingroup\catcode`\&=3 -\long\gdef\ettl@getlistitem#1#2{%#1=listmacro, #2=index - \ettl@get@list@item{#1}{\number\numexpr#2}} +\long\gdef\ettl@getlistitem#1#2#3{%#2=index, #3=list or list-macro + #1\ettl@get@list@item{#3}{\numexpr#2}} \long\gdef\ettl@get@list@item#1#2{% \ifblank{#1}{} {\ifnum#2=1 \ettl@afterelsefi - \expandonce{\ettl@list@first@item#1&} + \expandonce{\ettl@list@first@item#1&}% \else\ifnum#2>0 \ettl@afterfifi - \expandnext\ettl@getlistitem{\ettl@list@other@item#1&}{#2-1}% + \expandnext\ettl@get@list@item{\ettl@list@other@item#1&}{#2-1}% \fi\fi}} \endgroup % \end{macrocode} % \end{macro} % -% \end{ltxsyntax} +% \iffalse +%<package> +%<package> +%<package>% \getcsvlistitem{ number }{ csvlistmacro } +%<package>% \getcsvlistitem*{ number }{ item,item,item,... } +% \fi +% \begin{macro}{\getcsvlistitem}\cmdlabel{impl:getcsvlistitem} +% \strut\seedesc{getcsvlistitem} +% \begin{macrocode} +\newcommand\getcsvlistitem[1]{\FE@ifstar{#1}{\ettl@getcsvlistitem{}} + {\ettl@getcsvlistitem\expandnext}} +\begingroup\catcode`\&=3 +\long\gdef\ettl@getcsvlistitem#1#2#3{%#2=index, #3=list or list-macro + #1\ettl@get@csvlist@item{#3,}{\numexpr#2}} +\long\gdef\ettl@get@csvlist@item#1#2{% + \ifblank{#1}{} + {\ifnum#2=1 \ettl@afterelsefi + \expandonce{\ettl@csvlist@first@item#1&}% + \else\ifnum#2>0 \ettl@afterfifi + \expandnext\ettl@get@csvlist@item{\ettl@csvlist@other@item#1&}{#2-1}% + \fi\fi}} +\endgroup +% \end{macrocode} +% \end{macro} +% +% \iffalse +%<package> +%<package> +%<package>% \gettokslistitem{ number }{ tokslistmacro } +%<package>% \gettokslistitem*{ number }{ list of tokens } +% \fi +% \begin{macro}{\gettokslistitem}\cmdlabel{impl:gettokslistitem} +% \strut\seedesc{gettokslistitem} +% \begin{macrocode} +\newcommand\gettokslistitem[1]{\FE@ifstar{#1}{\ettl@gettokslistitem{}} + {\ettl@gettokslistitem\expandnext}} +\begingroup\catcode`\&=3 +\long\gdef\ettl@gettokslistitem#1#2#3{%#2=index, #3=list or list-macro + #1\ettl@get@tokslist@item{#3{}}{\numexpr#2}} +\long\gdef\ettl@get@tokslist@item#1#2{% + \ifblank{#1}{} + {\ifnum#2=1 \ettl@afterelsefi + \expandonce{\ettl@tokslist@first@item#1&}% + \else\ifnum#2>0 \ettl@afterfifi + \expandnext\ettl@get@tokslist@item{\@gobble#1}{#2-1}% + \fi\fi}} +\endgroup +% \end{macrocode} +% \end{macro} +% +% +% +% +% +% \iffalse +%<package>%---------------------------------------------------------------------------- +%<package> +%<package>% \collectoks{ cs-token }{ list of allowed tokens }{ commands to expand after } +%<package> +% \fi +% \begin{macro}{\collecttoks}\cmdlabel{impl:collecttoks} +% A simple token scanner, vectorized version of \cs{futurelet}.\seedesc{collecttoks} +% \begin{macrocode} +\newrobustcmd*\collecttoks{\@ifstar\ettl@scantoks\ettl@collecttoks} +\def\ettl@scantoks{\@latex@error{The starred version of \noexpand\collecttoks + \MessageBreak (i.e. scantoks) is NOT implemented YET.}\@ehd} +% \end{macrocode} +% \end{macro} +% +% \iffalse +%<package> +% \fi +% +% \begin{macro}{\ettl@collecttoks} +% \begin{macrocode} +\def\ettl@collecttoks#1#2#3{\begingroup + \def\ettl@collecttoks@list{#2}% + \let#1=\@empty + \def\Next{\ettl@collect@toks{#1}}% + \def\finale{#3}% + \futurelet\ettl@x\Next} +\def\ettl@collect@toks#1{% + \edef\ettl@i{\gettokslistindex\ettl@x\ettl@collecttoks@list}% + \ifcase\ettl@i \edef\next{\endgroup + \def\noexpand#1{\expandonce{#1}}\expandonce{\finale}}% + \else \def\next{\ettl@collect@toks@next{#1}}% + \fi\next} +\def\ettl@collect@toks@next#1#2{% + \edef#1{\expandonce{#1}\unexpanded{#2}}% + \futurelet\ettl@x\Next} +% \end{macrocode} +% \end{macro} +% +% % % \begin{macrocode} %</package> @@ -1199,10 +1777,10 @@ and etextools-examples.tex \usepackage[latin1]{inputenc} \usepackage[T1]{fontenc} \usepackage[american]{babel} -\usepackage{geometry,doc,ltxdockit,txfonts,fancyhdr} +\usepackage{geometry,doc,ltxdockit,txfonts,fancyhdr,stmaryrd,graphicx,fancyvrb} \usepackage{etextools} \hypersetup{colorlinks,pdfstartview={FitH}} -\geometry{top=2cm,bottom=2cm,left=2.5cm,right=1cm} +\geometry{top=1.5cm,bottom=1.2cm,left=2.5cm,right=1cm} \fancyhf{} \fancyhead[L]{Examples for the \sty{etextools} package} \pagestyle{fancy} @@ -1210,6 +1788,9 @@ and etextools-examples.tex \makeatletter \def\smex{\leavevmode\hb@xt@2em{\hfil$\longrightarrow$\hfil}} +\def\FE{\setbox8\hbox{$\m@th\bindnasrepma$}% + \textcolor{fecc}{\scalebox{2}{$\copy8\mkern-13.5mu\copy8\mkern-13.5mu\copy8$}}} +\definecolor{fecc}{rgb}{.2,.6,.2} \def\strip@meaning{\expandafter\strip@prefix\meaning} \def\strip@macro{\expandafter\strip@macroprefix\meaning} \def\get@params#1{\expandafter\@get@params\meaning#1\@nil} @@ -1222,16 +1803,19 @@ and etextools-examples.tex \def\meaningcs#1{\expandafter\meaning\csname#1\endcsname} \def\Meaningcs#1{\expandafter\strip@meaning\csname #1\endcsname} +\@ifundefined{pdfstrcmp}{\let\ifpdfTeX\iffalse}{\let\ifpdfTeX\iftrue} -\newcommand\test[1]{% +\newcommand*\test{\@ifstar{\let\fe\relax\testi}{\let\fe\FE\testi}} +\newcommand\testi[1]{% \csname test#1\endcsname \edef\usercmd{\Meaningcs{test#1}}\edef\result{\meaningcs{#1Test}}\noindent \begin{tabular}{lp{15cm}} - \multicolumn{2}{l}{\textcolor{blue}{\llap\smex\tt \usercmd}} \\[1.5ex] + \multicolumn{2}{l}{\textcolor{blue}{\llap{\fe\,\smex}\tt \usercmd}} \\[1.5ex] \cmd{#1Test}= & \tt\bfseries\result \end{tabular}\par\nobreak\hrulefill\null\goodbreak} + \begin{document} \title{etextools examples} \subtitle{Examples for some macros provided by the \sty{etextools} package} @@ -1335,8 +1919,11 @@ and etextools-examples.tex \hrulefill\par \test{FE@testopt} + \section{Lists management} + \subsection{\cmd{csvloop} and \cmd{csvloop*} examples} + \subsubsection{\cmd{makequotes}} \def\makequotes#1{"#1"\space} \def\testcsvloop{% @@ -1344,11 +1931,13 @@ and etextools-examples.tex } \preline\makequotes \test{csvloop} + \subsubsection{\cmd{detokenize}} \def\testcsvloop{% \edef\csvloopTest{\csvloop*[\detokenize]{\un,\deux}} }\hrulefill\par \test{csvloop} + \subsubsection{\cmd{numexpr}} \def\mylist{1,2,3,4,5}\def\BySeven#1{$#1\times 7 = \number\numexpr#1*7\relax$\par} \def\testcsvloop{% @@ -1356,26 +1945,94 @@ and etextools-examples.tex \preline\mylist \preline*\BySeven \test{csvloop} + \subsubsection{protected \cmd{textbf}} \def\testcsvloop{% \protected@edef\csvloopTest{\csvloop*[\textbf]{hello ,my ,friends}} }\hrulefill\par \test{csvloop} -\subsection{\cmd{getlistitem}} +\subsection{Index in lists and items by index} + +\subsubsection{\cmd{getlistitem}} \csvtolist*\mylist{one,two,three,four,five,alpha,beta,gamma} \def\testgetlistitem{% - \edef\getlistitemTest{\getlistitem\mylist{4}} + \edef\getlistitemTest{\getlistitem{4}\mylist} }\hrulefill\par \noindent\hskip6pt|\csvtolist*\mylist{one,two,three,four,five,alpha,beta,gamma}|\par\vskip1.5ex \test{getlistitem} -\subsection{\cmd{getlistindex} {\mdseries(not expandable)}} -\getlistindex{four}\mylist +\subsubsection{\cmd{getlistindex}} +\ifpdfTeX +\leavevmode\vadjust{\textsl{Require the }\string\pdfstrcmp\ \textsl{primitive (pdf\TeX{}) :}} +\def\testgetlistindex{% + \edef\getlistindexTest{\getlistindex{alpha}\mylist} +}\hrulefill\par +\noindent\hskip6pt|\csvtolist*\mylist{one,two,three,four,five,alpha,beta,gamma}|\par\vskip1.5ex +\test{getlistindex} + +\leavevmode\vadjust{\textsl{Require the }\string\pdfstrcmp\ \textsl{primitive (pdf\TeX{}) :}} +\def\testgetlistindex{% + \edef\getlistindexTest{\getcsvlistindex*{alpha}{one,two,three,four,five,alpha,beta}} +}\hrulefill\par +\test{getlistindex} +\fi + +\hrulefill\par +\getlistindex[\myindex]{alpha}\mylist +{\color{blue}\noindent\hskip6pt\llap\smex|\getlistindex[\myindex]{alpha}\mylist|\par\vskip1.5ex} +{\tt\string\myindex=\quad\textbf{\meaning\myindex}} +\hrulefill\par\vskip.5ex + \hrulefill\par +\newcount\myindex +\getcsvlistindex*[\myindex]{alpha}{one,two,three,four,five,alpha,beta} +\noindent\hskip6pt|\newcount\myindex|\par +{\color{blue}\noindent\hskip6pt\llap\smex|\getcsvlistindex*[\myindex]{alpha}{one,two,three,four,five,alpha,beta}|}\par\vskip.5ex +{\tt\string\the\string\myindex=\qquad\textbf{\the\myindex}} +\hrulefill\par\vskip.5ex + + +\subsubsection{\cmd{xgetlistindex}} +\ifpdfTeX +\leavevmode\vadjust{\textsl{Require the }\string\pdfstrcmp\ \textsl{primitive (pdf\TeX{}) :}} +\def\x{beta} +\def\testxgetlistindex{% + \edef\xgetlistindexTest{\xgetlistindex{\x}\mylist} +}\hrulefill\par \noindent\hskip6pt|\csvtolist*\mylist{one,two,three,four,five,alpha,beta,gamma}|\par\vskip1.5ex -\noindent\hskip6pt\textcolor{blue}{\llap\smex\cmd{getlistindex}\string{four\string}\cmd{mylist}}\par\vskip1.5ex -\noindent\hskip6pt\cmd{indexinlist}=\quad{\bfseries\meaning\indexinlist}\par\hrulefill\par +\preline*\x +\test{xgetlistindex} +\fi + +\subsubsection{\cmd{getlistindex} with \cmd{ifcase}} + +\leavevmode\vadjust{Always purely expandable (no need of |\pdfstrcmp|, comparison done by |\ifx|):} +\hrulefill\par\noindent +\llap{\FE\,\smex}\par\vskip-2.5\baselineskip\strut +\begin{Verbatim} + \ifcase \gettokslistindex*{D}{LRDF\relax O} + Problem + \or What do to if L + \or What do to if R + \or What do to if D + \or What do to if F + \or What do to if \relax + \or What do to if O + \fi +\end{Verbatim} + +{\tt Result=\qquad\bfseries +\ifcase\gettokslistindex*{D}{LRDF} + Problem +\or What do to if L +\or What do to if R +\or What do to if D +\or What do to if F +\fi}\par +\hrulefill\par\vskip.5ex + + \end{document} %</example> @@ -1383,12 +2040,36 @@ and etextools-examples.tex % % \section{Revision history} % -% \begin{changelog} +% \begin{changelog}\footnotesize % -% \begin{release}{2z}{2009-08-12} -% \item Addition of \cmdref{ifempty} +% \begin{release}{2t}{2009-08-15} +% \item +% Addition of \cmdref{ifnotempty}, \cmdref{iflastchar}, \cmdref{ifstrcmp}, \cmdref{ifstrmatch} +% +% +% \end{release} +% +% \begin{release}{2h}{2009-08-14} +% \item +% \cmdref{getlistindex} is now fully expandable % -% \item Modification of \cmdref{ifsinglechar}\\ +% \item Addition of\\ +% \cmdref{toksloop} and \cmd{toksloop*} \\ +% \cmdref{tokstolist} and \cmd{tokstolist*} \\ +% \cmdref{getcsvlistindex} and \cmdref{getcsvlistitem} \\ +% \cmdref{gettokslistindex} and \cmdref{gettokslistitem} \\ +% +% \item Addition of\\ +% \cmdref{collecttoks} -- a vectorized version of \cs{futurelet}.\\ +% \cmdref{FE@ifchar} as a generalization of \cmdref{FE@ifstar}. +% +% \end{release} +% +% \begin{release}{2z}{2009-08-12} +% \item Addition of \\ +% \cmdref{ifempty}, \cmdref{toksloop}, \cmdref{tokstolist} and \cmdref{tokstolistadd} +% \item +% Modification of \cmdref{ifsinglechar}\\ % |\ifsinglechar| now works with |\ifempty| so that:\\ % \begin{tabbing} % \quad\=|\macro{ * }|\quad\= is no more considered as a starred form \\ @@ -1397,11 +2078,13 @@ and etextools-examples.tex % \>\>as does |\@ifnextchar| from the \LaTeX{} kernel. % \end{tabbing} % -% \item Index added to this documentation paper. +% \item +% Index added to this documentation paper. % \end{release} % \begin{release}{2e}{2009-07-14} -% \item First version (include an example file) +% \item +% First version (include an example file) % \end{release} % % \end{changelog} diff --git a/Master/texmf-dist/source/latex/etextools/etextools.ins b/Master/texmf-dist/source/latex/etextools/etextools.ins index ca83a61febb..f922c22757f 100644 --- a/Master/texmf-dist/source/latex/etextools/etextools.ins +++ b/Master/texmf-dist/source/latex/etextools/etextools.ins @@ -21,11 +21,11 @@ %% etextools.sty, etextools.pdf, etextools.ins, %% and etextools-examples.tex %% -%%% etextools : more e-TeX useful tools for LaTeX package writers +%%% etextools : more e-TeX useful tools for LaTeX package writers (v. \input docstrip.tex \Msg{************************************************************************} \Msg{* Installation} -\Msg{* Package: etextools 2009/07/14 v2e e-TeX more useful tools for LaTeX package writers} +\Msg{* Package: etextools 2009/07/14 v2h e-TeX more useful tools for LaTeX package writers} \Msg{************************************************************************} \keepsilent @@ -76,6 +76,7 @@ and etextools-examples.tex \endbatchfile + \endinput %% %% End of file `etextools.ins'. diff --git a/Master/texmf-dist/tex/latex/etextools/etextools.sty b/Master/texmf-dist/tex/latex/etextools/etextools.sty index e11696396a5..791e2fd2c1c 100644 --- a/Master/texmf-dist/tex/latex/etextools/etextools.sty +++ b/Master/texmf-dist/tex/latex/etextools/etextools.sty @@ -21,29 +21,45 @@ %% etextools.sty, etextools.pdf, etextools.ins, %% and etextools-examples.tex %% -%%% etextools : more e-TeX useful tools for LaTeX package writers +%%% etextools : more e-TeX useful tools for LaTeX package writers (v. + \NeedsTeXFormat{LaTeX2e}[1996/12/01] \ProvidesPackage{etextools} - [2009/07/14 v2e e-TeX more useful tools for LaTeX package writers] + [2009/08/14 v2h e-TeX more useful tools for LaTeX package writers] \csname ettl@onlyonce\endcsname\let\ettl@onlyonce\endinput \RequirePackage{etex,etoolbox} -\edef\ettl@restore@space@catcode{\catcode`\ =\the\catcode`\ } -\AtEndOfPackage{\ettl@restore@space@catcode - \let\ettl@restore@space@catcode\ettl@undefined} -\catcode`\ =10 +\let\ettl@AtEnd\@empty +\def\TMP@EnsureCode#1#2{% + \edef\ettl@AtEnd{% + \ettl@AtEnd + \catcode#1 \the\catcode#1\relax + }% + \catcode#1 #2\relax +} +\TMP@EnsureCode{32}{10}% space +\ifundef\pdfstrcmp{% + \TMP@EnsureCode{33}{9}% ! ignore + \TMP@EnsureCode{34}{14}% " comment +}{\TMP@EnsureCode{33}{14}% ! comment + \TMP@EnsureCode{34}{9}% " ignore +} +\AtEndOfPackage{\ettl@AtEnd\undef\ettl@AtEnd} % A few helper macros \long\def\ettl@afterelse#1\else#2\fi{\fi#1} \long\def\ettl@afterfi#1\fi{\fi#1} \long\def\ettl@afterfifi#1\fi\fi{\fi\fi#1} \long\def\ettl@afterelsefi#1\else#2\fi\fi{\fi#1} -\begingroup\catcode`\|=4 -\long\gdef\ettl@cdr#1#2|{#2} -\endgroup +\long\def\ettl@afterorfi#1\or#2\fi{\fi#1} +\def\ettl@ifstrcmp#1#2{\csname @% + \ifnum\pdfstrcmp{#1}{#2}=0 first\else second\fi oftwo\endcsname} \newcommand*\@gobblescape{\expandafter\@gobble\string} -\newcommand\str@gobblescape[1]{\expandafter\deblank\expandafter{% - \expandafter\@gobble\detokenize{#1}}} +\def\ettl@onlypdfTeX#1#2{\ifundef{#1} + {\def#2{\PackageError{etextools}{\string#1\space primitive not found\MessageBreak + pdfTeX seems not to be running} + {\string#2\space works only if used with pdfTeX (requires \string#1)}}} + {}} \newcommand*\noexpandcs[1]{\expandafter\noexpand\csname #1\endcsname} \newcommand\noexpandafter{\noexpand\expandafter} @@ -64,47 +80,94 @@ \expandafter\ettl@afterfi#2#1#2{#3}% \fi} -\newcommand\deblank{} -\newcommand\ifempty{} -\begingroup\catcode`\|=4% a | as a tab array -\long\gdef\deblank#1{\@deblank#1 |} -\long\gdef\@deblank#1 #2|{\ifblank{#2}{#1}{#1\@deblank#2 |}} % \ifempty{ text }{ true }{ false } -\long\gdef\ifempty#1{\csname @\ifx|#1|first\else second\fi oftwo\endcsname} -\endgroup% catcode group +\newcommand\ifempty[1]{\csname @\expandafter\ifx + \expandafter\relax\detokenize{#1}\relax + first\else second\fi oftwo\endcsname} + +% \ifnotempty{ text }{ true }{ false } +\newcommand\ifnotempty[1]{\csname @\expandafter\ifx + \expandafter\relax\detokenize{#1}\relax + second\else first\fi oftwo\endcsname} + +% \xifempty{ text }{ true }{ false } +\newcommand\xifempty[1]{\xifstrcmp{#1}{}} +\ettl@onlypdfTeX\pdfstrcmp\xifempty + +% \ifnotblank{ text }{ true }{ false } +\begingroup\catcode`\&=3\catcode`\:=12 +\ifcsundef{ifnotblank}{% +\long\gdef\ifnotblank#1{\etb@ifblank@i#1&&\@firstoftwo\@secondoftwo:}} +\relax\endgroup +% \xifblank{ string }{ true }{ false } \newrobustcmd\xifblank[1]{\begingroup \protected@edef\@xifblank{\endgroup \noexpand\ifblank{#1}% }\@xifblank} -\newrobustcmd\xifstrequal[2]{% - \begingroup\protected@edef\@tempa{#1}\protected@edef\@tempb{#2}% - \ifx\@tempa\@tempb \aftergroup\@firstoftwo - \else \aftergroup\@secondoftwo - \fi\endgroup} -\newcommand\iffirstchar[2]{% - \if \expandafter\@car\string#2\relax\@nil\expandafter\@car#1\string\\\@nil - \ettl@afterelse\ifblank{#2}\@secondoftwo\@firstoftwo - \else \expandafter\@secondoftwo - \fi} -\newcommand\ifsinglechar{} -\begingroup\catcode`\|=4 -\long\gdef\ifsinglechar#1#2{% - \csname @\expandafter\expandafter\expandafter\ifx - \expandafter\expandafter\expandafter|% - \expandafter\ettl@cdr\string#2||first\else second\fi - oftwo\endcsname - {\iffirstchar{#1}{#2}} - \@secondoftwo} -\endgroup% catcode group -%\FE@testopt{#1}{commands}{default option} +% \iffirstchar{ string1 }{ string2 }{ true }{ false } +\newcommand\iffirstchar[2]{\csname @% + \if \expandafter\@car\detokenize{#2}\relax\@nil\expandafter\@car\detokenize{#1}\string\\\@nil + \ifblank{#2}{second}{first}% + \else second% + \fi oftwo\endcsname} + +% \ifsinglechar character{ string }{ true }{ false } +\newcommand\ifsinglechar[2]{% + \csname @\ifblank{#2}{second}{% +" \ifnum\pdfstrcmp{\detokenize{#1}}{\detokenize{#2}}=0 +" \ifnum\pdfstrcmp{\detokenize{#2}}{\expandafter\@car\detokenize{#2}\relax\@nil}=0 +" first% +" \else second% +" \fi +" \else second% +" \fi oftwo\endcsname}} +! \expandafter\expandafter\expandafter\ifx +! \expandafter\expandafter\expandafter\relax\expandafter\@cdr\detokenize{#2}\@nil\relax +! \iffirstchar{#1}{#2}{first}{second}\else second\fi oftwo\endcsname}} + +% \iflastchar{ string1 }{ string2 }{ true }{ false } +\begingroup\catcode`\&=3 +\long\gdef\iflastchar#1#2{% + \long\def\ettl@iflastchar##1#1##2&{% + \ifstrcmp{##2}{#1}\@firstoftwo{% + \ifempty{##2}\@secondoftwo{\ettl@iflastchar##2&}} + }\ettl@iflastchar#2#1&} +\endgroup + +% \ifstrcmp{ string1 }{ string2 }{ true }{ false } +\newcommand\ifstrcmp[2]{\csname @% + \ifnum\pdfstrcmp{\detokenize{#1}}{\detokenize{#2}}=0 first\else second\fi + oftwo\endcsname} +\ettl@onlypdfTeX\pdfstrcmp\ifstrcmp + +% \xifstrcmp{ string1 }{ string2 }{ true }{ false } +\newcommand\xifstrcmp[2]{\csname @% + \ifnum\pdfstrcmp{#1}{#2}=0 first\else second\fi + oftwo\endcsname} +\ettl@onlypdfTeX\pdfstrcmp\ifxstrcmp +\newrobustcmd*\xifstrequal[2]{\begingroup + \protected@edef\@xifstrequal{\endgroup\noexpand\ifstrequal{#1}{#2}% + }\@xifstrequal} + +% \ifstrmatch{ pattern }{ true }{ false } +\newcommand\ifstrmatch[2]{\csname @% + \ifnum\pdfmatch{\detokenize{#1}}{\detokenize{#2}}=1 first\else second\fi + oftwo\endcsname} +\ettl@onlypdfTeX\pdfmatch\ifstrmatch +%---------------------------------------------------------------------------- +% Purely Expandable Macros With Options / Star Forms / Variants +% \FE@testopt{ #1 }{ commands }{ default option } \newcommand\FE@testopt[3]{\ifsinglechar [{#1}{#2#1}{#2[{#3}]{#1}}} -%\FE@ifstar{#1}{\StarredMacro}{\NotStarredMacro} +% \FE@ifstar{ #1 } { \StarredMacro }{ \NotStarredMacro } \newcommand\FE@ifstar[3]{\ifsinglechar *{#1}{#2}{#3{#1}}} +% \FE@ifchar{#1}{#2}{ \SpecialFormMacro }{ \NormalMacro } +\newcommand\FE@ifchar[4]{\ifsinglechar{#1}{#2}{#3}{#4{#2}}} + %% \iffalse % \DeclareCmdListParser : general constructor for command-list parsers @@ -118,16 +181,12 @@ \def\`##1`{\expandafter\noexpand\csname ##1\endcsname}% \protected@edef\defineparser{\endgroup \long\def#1####1{\noexpand\FE@ifstar{####1} - {\`ettl@lst@star\string#1`} - {\`ettl@lst@nost\string#1`}}% - \long\csdef{ettl@lst@star\string#1}####1{\noexpand\FE@testopt{####1} - {\`ettl@lst@star@pt\string#1`}{\noexpand\do}}% - \long\csdef{ettl@lst@nost\string#1}####1{\noexpand\FE@testopt{####1} - {\`ettl@lst@nost@pt\string#1`}{\noexpand\do}}% - \long\csdef{ettl@lst@star@pt\string#1}[####1]####2{% - \`ettl@lst\string#1`{####2}{####1}}% - \long\csdef{ettl@lst@nost@pt\string#1}[####1]####2{% - \noexpandafter\`ettl@lst\string#1`\noexpandafter{####2}{####1}}% + {\`ettl@lst@opt\string#1`{}} + {\`ettl@lst@opt\string#1`\noexpandafter}}% + \long\csdef{ettl@lst@opt\string#1}####1####2{\noexpand\FE@testopt{####2} + {\`ettl@lst@@pt\string#1`{####1}}{\noexpand\do}}% + \long\csdef{ettl@lst@@pt\string#1}####1[####2]####3{% + ####1\`ettl@lst\string#1`####1{####3}{####2}}% \long\csdef{ettl@lst\string#1}####1####2{% \`ettl@lst@\string#1`{####2}####1\unexpanded{#2}&}% \long\csdef{ettl@lst@\string#1}####1####2\unexpanded{#2}####3&{% @@ -149,20 +208,29 @@ \begingroup\catcode`\|=3 \def\do{\DeclareCmdListParser\listloop{|}}% \expandafter\endgroup\do +\DeclareCmdListParser\toksloop{}% + +% \csvtolist \ListMacro \csvListMacro +% \csvtolist* \ListMacro {item,item,item} +\newrobustcmd*\csvtolist{\@ifstar + {\ettl@tolist\z@{}\csvloop} + {\ettl@tolist\z@\expandnext\csvloop}}% +\long\def\ettl@tolist#1#2#3#4#5{\ifx#1\z@\let#4\@empty\fi + \def\ettl@to@list{#3*[{\unexpanded{\listadd#4}}]% + }#2\ettl@to@list{#5}} -%\csvtolist\csvListMacro -%\csvtolist*{item,item,item} -\newcommand\csvtolist{\@ifstar\star@csvtolist\nost@csvtolist}% -\def\star@csvtolist#1{\let#1\@empty\csvloop*[{\unexpanded{\listadd#1}}]}% -\def\nost@csvtolist#1{\let#1\@empty\csvloop[{\unexpanded{\listadd#1}}]}% +\newrobustcmd*\tokstolist{\@ifstar{\ettl@tokstolist\z@{}}{\ettl@tokstolist\z@\expandnext}} +\def\ettl@tokstolist#1#2#3#4{\ifx#1\z@\let#3\@empty\fi + \def\ettl@toks@tolist{\toksloop*[{\unexpanded{\listadd#3}}]}% + #2\ettl@toks@tolist{#4{}}} -%\csvtolistadd\csvListMacro -%\csvtolistadd*{item,item,item} -\newcommand\csvtolistadd{\@ifstar\star@csvtolistadd\nost@csvtolistadd}% -\def\star@csvtolistadd#1#2{\ifblank{#2} - {\let#1\@empty}{\csvloop*[{\unexpanded{\listadd#1}}]{#2}}}% -\def\nost@csvtolistadd#1#2{\ifblank{#2} - {\let#1\@empty}{\csvloop[{\unexpanded{\listadd#1}}]{#2}}}% +% \csvtolistadd \ListMacro \csvListMacro +% \csvtolistadd* \ListMacro {item,item,item} +\newrobustcmd*\csvtolistadd{\@ifstar + {\ettl@tolist\@ne{}\csvloop} + {\ettl@tolist\@ne\expandnext\csvloop}} + +\newrobustcmd*\tokstolistadd{\@ifstar{\ettl@tokstolist\@ne{}}{\ettl@tokstolist\@ne\expandnext}}% %\listdel\listMacro{item} %\listgdel\listMacro{item} @@ -181,11 +249,11 @@ \begingroup\catcode`\|=3\catcode`\&=3 \long\gdef\@listdel#1#2#3{% \begingroup - \def\@tempa##1|#3|##2&{##1|##2\@tempb}% - \def\@tempb|##1|\@tempb##2|\@tempb{% + \long\def\@tempa##1|#3|##2&{##1|##2\@tempb}% + \long\def\@tempb|##1|\@tempb##2|\@tempb{% \ifblank{##2}{\unexpanded{##1}} {\ifblank{##1}{}{\@tempx##1&}}}% - \def\@tempx##1&{\expandafter\@tempb\@tempa|##1|\@tempb|#3|&}% + \long\def\@tempx##1&{\expandafter\@tempb\@tempa|##1|\@tempb|#3|&}% \edef\@redef{\endgroup \unexpanded{#1#2}{% ie: \def or \gdef \listmacro \expandafter\@tempx\unexpanded\expandafter{#2}&}% @@ -193,39 +261,153 @@ \endgroup -% \getlistindex (result in \indexinlist) +% \getlistindex[\indexmacro]{ \listmacro } +% \getlistindex*[\indexmacro]{ expanded list } +\newcommand\getlistindex[1]{\FE@ifstar{#1} + {\ettl@getlistindex{}\unexpanded} + {\ettl@getlistindex\expandnext\unexpanded}} +\newcommand\xgetlistindex[1]{\FE@ifstar{#1} + {\ettl@getlistindex{}\@firstofone} + {\ettl@getlistindex\expandnext\@firstofone}} \begingroup\catcode`\|=3\catcode`\&=3 -\gdef\getlistindex#1{\FE@ifstar{#1}{\ettl@getlistindex{}} - {\ettl@getlistindex\expandnext}} -\gdef\xgetlistindex#1{\FE@ifstar{#1}{\ettl@xgetlistindex{}} - {\ettl@xgetlistindex\expandnext}} -\gdef\ettl@xgetlistindex#1#2#3{\begingroup - \protected@edef\next{\endgroup\unexpanded{\ettl@getlistindex{#1}{#2}}{#3}% - }\next} -\gdef\ettl@getlistindex#1#2#3{\begingroup#1\ettl@get@list@idx{#3}{#2}{\numexpr1}} -\gdef\ettl@get@list@idx#1#2#3{% #1=expanded list, #2=item, #3=index +\long\gdef\ettl@getlistindex#1#2#3{\FE@testopt{#3}{\ettl@get@listindex{#1}{#2}}{}} +\long\gdef\ettl@get@listindex#1#2[#3]#4#5{#1\ettl@get@list@idx{#5}{#4}{\numexpr1}{#2}[{#3}]} +\long\gdef\ettl@get@list@idx#1#2#3#4[#5]{% #1=expanded list, #2=item, #3=index, #4=\unexpanded (event., #5=indexmacro) + \ifblank{#1}0% the (remainder of) the list is empty +" {\xifstrcmp{\expandonce{\ettl@list@first@item#1&}}{#4{#2}}} +! {\ettl@listitem@cmp{\ettl@list@first@item#1&}{#2}{#4}} + {\ifblank{#5}{\number#3\relax}{\ettl@ifiscount{#5}{#5=\number#3\relax}{\edef#5{\number#3}}}} + {\expandnext\ettl@get@list@idx{\ettl@list@other@item#1&}{#2}{#3+1}{#4}[{#5}]}} +\long\gdef\ettl@list@first@item#1|#2&{#1} +\long\gdef\ettl@list@other@item#1|#2&{#2} +!\long\gdef\ettl@listitem@cmp#1#2#3{% +! \ifx#3\unexpanded\def\ettl@listitem@cmp@{#2}% +! \else\protected@edef\ettl@listitem@cmp@{#2}% +! \fi +! \expandafter\ifstrequal\expandafter{#1}{#2}} +\edef\ettl@ifiscount{% + \gdef\noexpand\ettl@ifiscount##1{% + \noexpand\expandafter\noexpand\ettl@ifiscount@i + \noexpand\meaning##1\string\count\noexpand\@nil}% +}\ettl@ifiscount +\edef\ettl@ifiscount@i{% + \gdef\noexpand\ettl@ifiscount@i##1\string\count##2\noexpand\@nil{% + \noexpand\ifempty{##1}}% +}\ettl@ifiscount@i + +%\getcsvlistindex{ item }{ csvlistmacro } +%\getcsvlistindex*{ item }{ item,item,item } +\long\gdef\getcsvlistindex#1{\FE@ifstar{#1} + {\ettl@getcsvlistindex{}\unexpanded} + {\ettl@getcsvlistindex\expandnext\unexpanded}} +\long\gdef\xgetcsvlistindex#1{\FE@ifstar{#1} + {\ettl@getcsvlistindex{}\@firstofone} + {\ettl@getcsvlistindex\expandnext\@firstofone}} +\long\gdef\ettl@getcsvlistindex#1#2#3{\FE@testopt{#3}{\ettl@get@csvlistindex{#1}{#2}}{}} +\long\gdef\ettl@get@csvlistindex#1#2[#3]#4#5{#1\ettl@get@csvlist@idx{#5}{#4}{\numexpr1}{#2}[{#3}]} +\long\gdef\ettl@get@csvlist@idx#1#2#3#4[#5]{% #1=expanded list, #2=item, #3=index, #4=\unexpanded (event., #5=indexmacro) + \ifblank{#1}0% the (remainder of) the list is empty +" {\xifstrcmp{\expandonce{\ettl@csvlist@first@item#1&}}{#4{#2}}} +! {\ettl@listitem@cmp{\ettl@csvlist@first@item#1&}{#2}{#4}} + {\ifblank{#5}{\number#3\relax}{\ettl@ifiscount{#5}{#5=\number#3\relax}{\edef#5{\number#3}}}} + {\expandnext\ettl@get@csvlist@idx{\ettl@csvlist@other@item#1&}{#2}{#3+1}{#4}[{#5}]}} +\long\gdef\ettl@csvlist@first@item#1,#2&{#1} +\long\gdef\ettl@csvlist@other@item#1,#2&{#2} + +%\gettokslistindex{ item }{ tokenslistmacro } +%\gettokslistindex*{ item }{ list of tokens } +\long\gdef\gettokslistindex#1{\FE@ifstar{#1} + {\ettl@gettokslistindex{}} + {\ettl@gettokslistindex\expandnext}} +\long\gdef\ettl@gettokslistindex#1#2{\FE@testopt{#2}{\ettl@get@tokslistindex{#1}}{}} +\long\gdef\ettl@get@tokslistindex#1[#2]#3#4{#1\ettl@get@tokslist@idx{#4}{#3}{\numexpr1}[{#2}]} +\long\gdef\ettl@get@tokslist@idx#1#2#3[#4]{% #1=expanded list, #2=item, #3=index \ifblank{#1}0% the (remainder of) the list is empty - {\expandnext\ifstrequal{\ettl@list@first@item#1&}{#2} - {\endgroup\edef\indexinlist{\number#3\relax}} - {\expandnext\ettl@get@list@idx{\ettl@list@other@item#1&}{#2}{#3+1}}}} -\gdef\ettl@list@first@item#1|#2&{#1} -\gdef\ettl@list@other@item#1|#2&{#2} + {\expandafter\ifx\expandafter#2\ettl@tokslist@first@item#1&% + \ettl@afterelse\ifblank{#4}{\number#3\relax} + {\ettl@ifiscount{#4}{#4=\number#3\relax}{\edef#4{\number#3}}}% + \else \ettl@afterfi + \expandnext\ettl@get@tokslist@idx{\ettl@tokslist@other@item#1&}{#2}{#3+1}[{#4}]% + \fi}} +\long\gdef\ettl@tokslist@first@item#1#2&{#1} +\long\gdef\ettl@tokslist@other@item#1#2&{#2} \endgroup% catcode group -\newcommand\getlistitem[1]{\FE@ifstar{#1}\ettl@getlistitem - {\expandnext\ettl@getlistitem}} + + +%\getlistitem{ number }{ listmacro } +%\getlistitem*{ number }{ listmacro } +\newcommand\getlistitem[1]{\FE@ifstar{#1}{\ettl@getlistitem{}} + {\ettl@getlistitem\expandnext}} \begingroup\catcode`\&=3 -\long\gdef\ettl@getlistitem#1#2{%#1=listmacro, #2=index - \ettl@get@list@item{#1}{\number\numexpr#2}} +\long\gdef\ettl@getlistitem#1#2#3{%#2=index, #3=list or list-macro + #1\ettl@get@list@item{#3}{\numexpr#2}} \long\gdef\ettl@get@list@item#1#2{% \ifblank{#1}{} {\ifnum#2=1 \ettl@afterelsefi - \expandonce{\ettl@list@first@item#1&} + \expandonce{\ettl@list@first@item#1&}% \else\ifnum#2>0 \ettl@afterfifi - \expandnext\ettl@getlistitem{\ettl@list@other@item#1&}{#2-1}% + \expandnext\ettl@get@list@item{\ettl@list@other@item#1&}{#2-1}% \fi\fi}} \endgroup +% \getcsvlistitem{ number }{ csvlistmacro } +% \getcsvlistitem*{ number }{ item,item,item,... } +\newcommand\getcsvlistitem[1]{\FE@ifstar{#1}{\ettl@getcsvlistitem{}} + {\ettl@getcsvlistitem\expandnext}} +\begingroup\catcode`\&=3 +\long\gdef\ettl@getcsvlistitem#1#2#3{%#2=index, #3=list or list-macro + #1\ettl@get@csvlist@item{#3,}{\numexpr#2}} +\long\gdef\ettl@get@csvlist@item#1#2{% + \ifblank{#1}{} + {\ifnum#2=1 \ettl@afterelsefi + \expandonce{\ettl@csvlist@first@item#1&}% + \else\ifnum#2>0 \ettl@afterfifi + \expandnext\ettl@get@csvlist@item{\ettl@csvlist@other@item#1&}{#2-1}% + \fi\fi}} +\endgroup + + +% \gettokslistitem{ number }{ tokslistmacro } +% \gettokslistitem*{ number }{ list of tokens } +\newcommand\gettokslistitem[1]{\FE@ifstar{#1}{\ettl@gettokslistitem{}} + {\ettl@gettokslistitem\expandnext}} +\begingroup\catcode`\&=3 +\long\gdef\ettl@gettokslistitem#1#2#3{%#2=index, #3=list or list-macro + #1\ettl@get@tokslist@item{#3{}}{\numexpr#2}} +\long\gdef\ettl@get@tokslist@item#1#2{% + \ifblank{#1}{} + {\ifnum#2=1 \ettl@afterelsefi + \expandonce{\ettl@tokslist@first@item#1&}% + \else\ifnum#2>0 \ettl@afterfifi + \expandnext\ettl@get@tokslist@item{\@gobble#1}{#2-1}% + \fi\fi}} +\endgroup +%---------------------------------------------------------------------------- + +% \collectoks{ cs-token }{ list of allowed tokens }{ commands to expand after } + +\newrobustcmd*\collecttoks{\@ifstar\ettl@scantoks\ettl@collecttoks} +\def\ettl@scantoks{\@latex@error{The starred version of \noexpand\collecttoks + \MessageBreak (i.e. scantoks) is NOT implemented YET.}\@ehd} + +\def\ettl@collecttoks#1#2#3{\begingroup + \def\ettl@collecttoks@list{#2}% + \let#1=\@empty + \def\Next{\ettl@collect@toks{#1}}% + \def\finale{#3}% + \futurelet\ettl@x\Next} +\def\ettl@collect@toks#1{% + \edef\ettl@i{\gettokslistindex\ettl@x\ettl@collecttoks@list}% + \ifcase\ettl@i \edef\next{\endgroup + \def\noexpand#1{\expandonce{#1}}\expandonce{\finale}}% + \else \def\next{\ettl@collect@toks@next{#1}}% + \fi\next} +\def\ettl@collect@toks@next#1#2{% + \edef#1{\expandonce{#1}\unexpanded{#2}}% + \futurelet\ettl@x\Next} + + \endinput %% %% End of file `etextools.sty'. |