From 3f39a4fbdf08fa724e5047b82e3437ddf9b83bf4 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Thu, 24 Sep 2009 00:09:27 +0000 Subject: etextools update (23sep09) git-svn-id: svn://tug.org/texlive/trunk@15437 c570f23f-e606-0410-a88d-b1316a301751 --- .../texmf-dist/tex/latex/etextools/etextools.sty | 1260 +++++++++++++++----- 1 file changed, 938 insertions(+), 322 deletions(-) (limited to 'Master/texmf-dist/tex') diff --git a/Master/texmf-dist/tex/latex/etextools/etextools.sty b/Master/texmf-dist/tex/latex/etextools/etextools.sty index 791e2fd2c1c..35f78a71ff1 100644 --- a/Master/texmf-dist/tex/latex/etextools/etextools.sty +++ b/Master/texmf-dist/tex/latex/etextools/etextools.sty @@ -21,13 +21,12 @@ %% etextools.sty, etextools.pdf, etextools.ins, %% and etextools-examples.tex %% -%%% etextools : more e-TeX useful tools for LaTeX package writers (v. - +%%% etextools : e-TeX tools for LaTeX Users and package Writers (v.3.0) \NeedsTeXFormat{LaTeX2e}[1996/12/01] \ProvidesPackage{etextools} - [2009/08/14 v2h e-TeX more useful tools for LaTeX package writers] + [2009/08/27 v3.0 e-TeX more useful tools for LaTeX package writers] \csname ettl@onlyonce\endcsname\let\ettl@onlyonce\endinput -\RequirePackage{etex,etoolbox} +\RequirePackage{etex,etoolbox,letltxmacro} \let\ettl@AtEnd\@empty \def\TMP@EnsureCode#1#2{% \edef\ettl@AtEnd{% @@ -36,376 +35,993 @@ }% \catcode#1 #2\relax } -\TMP@EnsureCode{32}{10}% space +\TMP@EnsureCode{32}{10}% space... just in case +\TMP@EnsureCode{47}{8}% / +\TMP@EnsureCode{167}{7}% § +\TMP@EnsureCode{164}{7}% ¤ +\TMP@EnsureCode{42}{12}% * +\TMP@EnsureCode{43}{12}% + +\TMP@EnsureCode{45}{12}% - +\TMP@EnsureCode{46}{12}% . +\TMP@EnsureCode{60}{12}% < +\TMP@EnsureCode{61}{12}% = +\TMP@EnsureCode{62}{12}% > +\TMP@EnsureCode{33}{12}% ! +\TMP@EnsureCode{152}{13}% ~ for the character test \ifundef\pdfstrcmp{% - \TMP@EnsureCode{33}{9}% ! ignore - \TMP@EnsureCode{34}{14}% " comment -}{\TMP@EnsureCode{33}{14}% ! comment - \TMP@EnsureCode{34}{9}% " ignore + \TMP@EnsureCode{163}{9}% £ ignore + \TMP@EnsureCode{128}{14}% \texteuro comment € +}{\TMP@EnsureCode{163}{14}% £ comment + \TMP@EnsureCode{128}{9}% \texteuro ignore } \AtEndOfPackage{\ettl@AtEnd\undef\ettl@AtEnd} % 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} -\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} -\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} +\let\ettl@ifdefined\iffalse%\ifdefined% turn to \iffalse to test other implementation on pdfTeX +\long\def\ettl@fi#1\fi{\fi#1} +\long\def\ettl@else#1\else#2\fi{\fi#1} +\long\def\ettl@or#1\or#2\fi{\fi#1} +\def\ettl@expandaftwo{\expandafter\expandafter\expandafter} +\def\ettl@expandafthree{\expandafter\expandafter\expandafter% + \expandafter\expandafter\expandafter\expandafter} +\cslet{ettl@1of1}\@firstofone %% for internal use only +\cslet{ettl@1of2}\@firstoftwo %% for internal use only +\cslet{ettl@2of2}\@secondoftwo %% for internal use only +\long\def\rmn@firstoftwo#1#2{\z@#1} %% for romannumeral +\long\def\rmn@secondoftwo#1#2{\z@#2}%% for romannumeral +\long\def\ettl@cdr#1#2\@nil{#2} %% \@cdr should be a LONG macro +\long\def\ettl@car#1#2\@nil{#1} %% \@car should be a LONG macro +\long\csdef{ettl@1of3}#1#2#3{#1} +\long\csdef{ettl@2of3}#1#2#3{#2} +\long\csdef{ettl@3of3}#1#2#3{#3} +\long\csdef{ettl@12of3}#1#2#3{{#1}{#2}} +\long\def\ettl@carcar#1#2#3#4{#4} +\long\def\ettl@firstspace#1#2#3{\expandafter\ettl@firstsp@ce\detokenize{#1} \\{#3}{#2}//} +\long\def\ettl@firstsp@ce#1 #2\\{\ettl@nbk#1//} +\long\def\ettl@csname#1\endcsname{\fi\endcsname}%% useful to get out of \if +\long\def\ettl@char#1{\csname ettl@\if\relax\expandafter\ettl@cdr\detokenize{#1}\@nil\relax + 1\else2\fi of2\endcsname} +\providecommand*\@intmax{2147483647} +\def\ettl@intmax{2147483647} + +%% \ettl@onlypdfTeX for internal use +\def\ettl@onlypdfTeX#1#2{\@testopt{\ettl@only@pdfTeX{#1}{#2}}{}} +\def\ettl@only@pdfTeX#1#2[#3]{\ifundef{#1} + {\ifblank{#3} + {\def#2{\PackageError{etextools}{\string#1\space primitive not found\MessageBreak + pdfTeX seems not to be running} + {\string#2\space works only if used with pdfTeX (requires \string#1)}}} + {\AtEndOfPackage{\let#2=#3}% + \PackageWarning{etextools}{\string#1\space primitive not found\MessageBreak + Macro \string#2\space has been replaced by \string#3\space\MessageBreak + It is not purely expandable}} + }\relax} + +%% \ettl@nbk argument to be tested//{ true }{ false }// +% `/` has a catcode of 3 all along this package +\long\def\ettl@nbk #1#2/#3#4#5//{#4} +\long\def\ettl@nbk@else#1#2/#3#4#5//#6\else#7\fi{\fi#4} +\long\def\ettl@ney#1//#2#3//{\romannumeral 0\csname @% + \if\relax\detokenize{#1}\relax first\else second\fi oftwo\endcsname + { #2}{ #3}} + +% The following macros are not used (here just for memory, in case of...) +\long\def\ettl@nbk@cat#1#2#3/#4#5#6//{\ettl@nbk#6//% + {\ifcat#1#2\ettl@else#5\else\ettl@fi#6\fi}{#5}//} +\long\def\ettl@nbk@ifx#1#2#3/#4#5#6//{\ettl@nbk#6//% + {\ifx#1#2\ettl@else#5\else\ettl@fi#6\fi}{#5}//} +\long\def\ettl@nbk@if#1#2#3/#4#5#6//% + {\ettl@nbk#6//{\if#1#2\ettl@else#5\else\ettl@fi#6\fi}{#5}//} +\long\def\ettl@nbk@IF[#1]#2#3#4/#5#6#7//{\ettl@nbk#7//% + {\csname if#1\endcsname\ettl@else#6\else\ettl@fi#7\fi}{#6}//} + +%% \@gobblespace and The Space Token +\long\def\@gobblespace#1 {#1} -% \expandnext : expansion control -% level 1 : \expandnext#1{...} <=> \expandafter#1\expandafter{...} -% level 2 : \expandnext\expandnext#1{...} etc. +%% \@gobblescape \cs-token +\newcommand*\@gobblescape{\romannumeral0\expandafter\@gobble\string} + +% The swap macros +\newcommand\@swap[2]{#2#1} +\@swap{ }{\let\ettl@sptoken= }% This makes \ettl@sptoken a space token +\newcommand\@swaparg[2]{#2{#1}} +\newcommand\@swaplast[3]{#1#3#2} +\newcommand\@swaptwo[2]{{#2}{#1}} + +%% \expandaftercmds : expansion control +% level 1 : \expandaftercmds { code }{ cs-token } +% level 2 : \expandaftercmds\expandaftercmds { code }{ cs-token } +\newcommand\expandaftercmds[2]{% + \ifsingletoken\expandaftercmds{#1} + {\expandafter@cmds{#2}{\expandafter\expandafter\expandafter}} + {\expandafter\@swap\expandafter{#2}{#1}}} +\long\def\expandafter@cmds#1#2#3{% + \ifsingletoken\expandafter@cmds{#1} + {\expandafter@cmds{#3}{\expandafter#2#2}} + {\@swap#2{#3}{#1}}} + +%% \expandnext : expansion control +% level 1 : \expandnext { code }{ control sequences : the first is expanded before code } +% level 2 : \expandnext\expandnext{ code }{ control sequences } \newcommand\expandnext[2]{% - \ifx#1\expandnext - \ettl@afterelse\expandafter\expandafter\expandafter - \expandafter\@expandnext{#2}{\expandafter\expandafter\expandafter}% - \else\ettl@afterfi\expandafter#1\expandafter{#2}% - \fi} + \ifsingletoken\expandnext{#1} + {\@expandnext{#2}{\expandafter\expandafter\expandafter}} + {\expandafter\@swaparg\expandafter{#2}{#1}}} \long\def\@expandnext#1#2#3{% - \ifx#1\expandnext - \expandafter\ettl@afterelse\expandafter\expandafter\expandafter - \expandafter\@expandnext{#3}{\expandafter#2#2}% - \else - \expandafter\ettl@afterfi#2#1#2{#3}% - \fi} + \ifsingletoken\expandnext{#1} + {\@expandnext{#3}{\expandafter#2#2}} + {#2\@swaparg#2{#3}{#1}}} +%% \expandnexttwo{ code }{ control sequences }{ control sequences } +\newcommand\expandnexttwo[3]{\expandnext{\expandnext{#1}{#2}}{#3}} -% \ifempty{ text }{ true }{ false } -\newcommand\ifempty[1]{\csname @\expandafter\ifx - \expandafter\relax\detokenize{#1}\relax +%% \ExpandAfter { code } { cs-token } +\newcommand\ExpandAftercmds[2]{\expandafter\@swap\expandafter{\romannumeral-`\q#2}{#1}} + +%% \ExpandNext { code } { argument } + % I'm not sure it is interesting to use \expandnext here... + %\newcommand\ExpandNext[2]{\expandnext{#1}{\romannumeral-`\q#2}} +\newcommand\ExpandNext[2]{\expandafter\@swaparg\expandafter{\romannumeral-`\q#2}{#1}} + +%% \ExpandNextTwo { code } { arg1 }{ arg2 } +\newcommand\ExpandNextTwo[3]{\ExpandNext{\ExpandNext{#1}{#2}}{#3}} + +% noexpandcs { csname } +\newcommand*\noexpandcs[1]{\expandafter\noexpand\csname #1\endcsname} + +% noexpandafter +\newcommand*\noexpandafter{\noexpand\expandafter} + +%% \showcs { csname } +\providecommand*\showcs[1]{\expandafter\show\csname#1\endcsname} + +%% \meaningcs { csname } +\providecommand\meaningcs[1]{\romannumeral-`\q + \csname\ifcsdef{#1}{ettl@meaningcs\endcsname{#1}} + {meaning\endcsname\@undefined}} +\def\ettl@meaningcs#1{\expandafter\meaning\csname#1\endcsname}% here we don't need \z@ to stop \romannumeral + % because \meaning is never blank nor begins with a space... + +%% \strip@meaning { cs-token } +%% \strip@meaningcs { csname } +\newcommand*\strip@meaning[1]{\romannumeral\csname\ifdef{#1}% + {\ifdefmacro{#1}{ettl@strip@meaning}{ettl@meaning}\endcsname#1}{z@\endcsname}} +\providecommand*\strip@meaningcs[1]{\romannumeral\csname\ifcsdef{#1}% + {\ifcsmacro{#1}{ettl@strip@meaning}{ettl@meaning}% + \expandafter\endcsname\csname#1\endcsname} + {z@\endcsname}} +\def\ettl@strip@meaning{\expandafter\expandafter\expandafter\z@% for \romannumeral in case the \meaning is blank... + \expandafter\strip@prefix\meaning} +\def\ettl@meaning{\expandafter\z@\meaning} + +%% \parameters@meaning { cs-token } +%% \parameters@meaningcs { csname } +\providecommand*\parameters@meaning[1]{} +\edef\parameters@meaning#1{\unexpanded{\romannumeral\expandafter + \expandafter\expandafter\z@\expandafter\ettl@params@meaning% + \meaning}#1\detokenize{macro:->}/} +\providecommand*\parameters@meaningcs[1]{} +\edef\parameters@meaningcs#1{\unexpanded{\romannumeral\ettl@expandafthree\z@ + \expandafter\expandafter\expandafter\ettl@params@meaning% + \expandafter\meaning\csname}#1\endcsname\detokenize{macro:->}/} +\edef\ettl@params@meaning{% + \def\noexpand\ettl@params@meaning\detokenize{macro:}##1\detokenize{->}##2/{##1}% +}\ettl@params@meaning + +%% \ifdefcount { cs-token }{ true }{ false } \FEII +%% \ifdefdimen { cs-token }{ true }{ false } \FEII +%% \ifdeftoks { cs-token }{ true }{ false } \FEII +%% \ifdefskip { cs-token }{ true }{ false } \FEII +%% \ifdefmuskip { cs-token }{ true }{ false } \FEII +%% \ifdefchar { cs-token }{ true }{ false } \FEII +%% \ifdefmathchar { cs-token }{ true }{ false } \FEII +\def\ettl@ifdef[#1]{\expandafter\ettl@ifd@f\expandafter{#1}} +\def\ettl@ifd@f#1#2{% + \csdef{ettl@ifdef#2}##1#1##2/End§Meaning/{\ettl@nbk##2//{\rmn@firstoftwo}{\rmn@secondoftwo}//} + \csedef{ifdef#2}##1{\noexpand\romannumeral\noexpandafter% + \noexpandcs{ettl@ifdef#2}\noexpand\meaning##1#1/End§Meaning/}%//{##2}{##3}//} +} +\ettl@ifdef[\string\count]{count} % defines \def\ifdefcount +\ettl@ifdef[\string\toks]{toks} % \def\ifdeftoks +\ettl@ifdef[\string\dimen]{dimen} % \def\ifdefdimen +\ettl@ifdef[\string\skip]{skip} % \def\ifdefskip +\ettl@ifdef[\string\muskip]{muskip} % \def\ifdefmuskip +\ettl@ifdef[\string\char]{char} % \def\ifdefchar +\ettl@ifdef[\string\mathchar]{mathchar} % \def\ifdefmathchar +\ettl@ifdef[\detokenize{blank space}]{blankspace}% \def\ifdefblankspace +\ettl@ifdef[\detokenize{the character}]{thechar}% \def\ifdefthechar +\ettl@ifdef[\detokenize{the letter}]{theletter} % \def\ifdeftheletter +\undef\ettl@ifdef\undef\ettl@ifd@f + +%% \avoidvoid [ replacement code ]{ cs-token / string } +%% \avoidvoid*[ replacement code ]{ cs-token / string } +\newcommand\avoidvoid[1]{\romannumeral\FE@ifstar{#1} + {\ettl@voidvoid{\ettl@ifdefempty\ifempty}} + {\ettl@voidvoid{\ettl@ifdefvoid\ifblank}}} +\long\def\ettl@voidvoid#1#2{\FE@testopt{#2}{\ettl@voidv@id#1}{}} +\long\def\ettl@voidv@id#1#2[#3]#4{\ifiscs{#4}{#1{#4}}{#2{#4}}{\z@#3}{\z@#4}} +\long\def\ettl@ifdefvoid#1{\csname @\ifx#1\relax first% + \else\expandafter\expandafter\expandafter\ettl@nbk\strip@meaning#1//{second}{first}//% + \fi oftwo\endcsname} +\long\def\ettl@ifdefempty#1{\expandafter\expandafter\expandafter\ifempty% + \expandafter\expandafter\expandafter{\strip@meaning#1}} + +%% \avoidvoidcs [ replacement code ]{ cs-name } +%% \avoidvoidcs*[ replacement code ]{ cs-name } +\newcommand\avoidvoidcs[1]{\romannumeral\FE@ifstar{#1} + {\ettl@avoidvoidcs{\ettl@ifdefempty}} + {\ettl@avoidvoidcs{\ettl@ifdefvoid}}} +\long\def\ettl@avoidvoidcs#1#2{\FE@testopt{#2}{\ettl@@voidvoidcs#1}{}} +\long\def\ettl@@voidvoidcs#1[#2]#3{\csname @\ifcsname#3\endcsname + \expandafter#1\csname#3\endcsname{first}{second}\else first\fi + oftwo\endcsname{\z@#2}{\z@\csname#3\endcsname}} + +%% The ifx-test and the character-test +\long\def\ettl@ifx#1#2#3#4{\ifx#1#2#3\else#4\fi} +\long\def\ettl@ifchar#1#2{\csname ettl@\if\noexpand#2\string#11of2\ettl@csname\fi + \unless\ifcat\noexpand#1\noexpand#22of2\ettl@csname\fi + \ifx#1#21\else2\fi of2\endcsname} + +%% \ifsingletoken{ tokenA }{ tokenB }{ true }{ false } +\newcommand\ifsingletoken[2]{\csname @\ettl@firstspace{#2} + {\ettl@nbk#1#2//{second}{\if\relax\detokenize{#1#2}\relax first\else\ifx#1#2first\else second\fi\fi}//} + {\if\relax\detokenize\expandafter{\ettl@cdr#2\@nil}\relax + \expandafter\ettl@ifxsingle + \else\expandafter\ettl@carcar + \fi{#1}{#2}{first}{second}}% + oftwo\endcsname} +\def\ettl@ifxsingle#1#2#3#4{\ettl@nbk#1//{\ifx#1#2#3\else#4\fi}{#4}//} + +%% \ifOneToken{ token }{ true }{ false } +\newcommand\ifOneToken[1]{\romannumeral\csname rmn@\ettl@firstspace{#1} + {\ettl@nbk#1//{second}{\if\relax\detokenize{#1}\relax second\else first\fi}//} + {\if\relax\detokenize\expandafter{\ettl@cdr#1\@nil}\relax + first\else second\fi}oftwo\endcsname} + +%% \ifsinglechar character{ string }{ true }{ false } +\newcommand\ifsinglechar[2]{\romannumeral\csname rmn@\ettl@firstspace{#2} + {\ettl@nbk#2//{second}{\if\relax\detokenize{#1#2}\relax first\else\ifx#1#2first\else second\fi\fi}//} + {\if\relax\detokenize\expandafter{\ettl@cdr#2\@nil}\relax + \expandafter\ettl@ifchar + \else\expandafter\ettl@carcar + \fi{#1}{#2}{first}{second}}% + oftwo\endcsname} + +%% \ifOneChar{ string }{ true }{ false } +\ettl@ifdefined\pdfmatch +\newcommand\ifOneChar[1]{\romannumeral\csname rmn@% + \ifnum\pdfmatch{\detokenize{^.$}}{\detokenize{#1}}=1 first\else second\fi + oftwo\endcsname} +\else +\newcommand\ifOneChar[1]{\romannumeral\csname rmn@\ettl@firstspace{#1} + {\ettl@nbk#1//{second}{\if\relax\detokenize{#1}\relax second\else first\fi}//} + {\if\relax\expandafter\ettl@cdr\detokenize{#1}\@nil\relax + first\else second\fi}oftwo\endcsname} +\fi%\pdfmatch + +%% \ifOneCharWithBlanks{ string }{ true }{ false } +\ettl@ifdefined\pdfmatch +\newcommand\ifOneCharWithBlanks[1]{\romannumeral\csname rmn@% + \ifnum\pdfmatch{\detokenize{^[[:space:]]*[^[:space:]][[:space:]]*$}}{\detokenize{#1}}=1 % + first\else second\fi oftwo\endcsname} +\else +\newcommand\ifOneCharWithBlanks[1]{\romannumeral\csname rmn@\ettl@nbk#1//% + {\expandafter\expandafter\expandafter\ettl@nbk + \expandafter\ettl@cdr\detokenize{#1}\@nil//{second}{first}//}% + {second}//oftwo\endcsname} +\fi + +%% \iffirstchar{ string1 }{ string2 }{ true }{ false } +\newcommand\iffirstchar[2]{\romannumeral\csname rmn@% + \ettl@nbk#2//% + {\ettl@nbk#1//% + {\expandnexttwo\ettl@ifchar{\ettl@car#2\@nil}{\ettl@car#1\@nil}{first}{second}} + {\if\relax\detokenize{#1}\relax secondoftwo\ettl@csname\fi + \ettl@firstspace{#2}{first}{second}}//}% + {\ettl@nbk#1//% + {\if\relax\detokenize{#2}\relax secondoftwo\ettl@csname\fi + \ettl@firstspace{#1}{first}{second}} + {\if\relax\detokenize{#1#2}\relax first\else second\fi}}//% + oftwo\endcsname} + +%% \ifiscs { string }{ true }{ false } +\newcommand\ifiscs[1]{\romannumeral\csname rmn@\ettl@nbk#1//% + {\if\relax\expandafter\ettl@cdr\detokenize{#1}\@nil\relax secondoftwo\ettl@csname\fi + \if\relax\detokenize\expandafter{\ettl@cdr#1\@nil}\relax + \expandafter\ettl@firstspace + \else secondoftwo\ettl@csname\fi{#1}{second}{first}} + {second}//oftwo\endcsname} + +%% \detokenizeChars { list of single tokens } +\newcommand\detokenizeChars[1]{\expandafter\ettl@dosinglelist + \expandafter\ettl@do@detokenChars\expandafter{\romannumeral0\protectspace{#1}}} +\long\def\ettl@do@detokenChars#1{\ifOneChar{#1}\detokenize\unexpanded{#1}} + +%% \protectspace { string } +\newcommand\protectspace[1]{\romannumeral\ettl@protectspace#1 /End§String/} +\long\def\ettl@protectspace#1 #2/End§String/{\ifempty{#2}{\z@#1} + {\expandafter\@swap\expandafter{\romannumeral\ettl@protectspace#2/End§String/}{\z@#1{ }}}} + +%% \ifempty{ text }{ true }{ false } +\newcommand\ifempty[1]{\romannumeral\csname rmn@\if\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 +%% \ifnotempty{ text }{ true }{ false } +\newcommand\ifnotempty[1]{\romannumeral\csname rmn@\if\relax\detokenize{#1}\relax second\else first\fi oftwo\endcsname} -% \xifempty{ text }{ true }{ false } +%% \xifempty{ text }{ true }{ false } \newcommand\xifempty[1]{\xifstrcmp{#1}{}} -\ettl@onlypdfTeX\pdfstrcmp\xifempty +\ettl@onlypdfTeX\pdfstrcmp\xifempty[\xifstrempty] -% \ifnotblank{ text }{ true }{ false } -\begingroup\catcode`\&=3\catcode`\:=12 -\ifcsundef{ifnotblank}{% -\long\gdef\ifnotblank#1{\etb@ifblank@i#1&&\@firstoftwo\@secondoftwo:}} -\relax\endgroup +%% \ifnotblank{ text }{ true }{ false } +\long\def\ifnotblank#1#2#3{\ettl@nbk#1//{#2}{#3}//} -% \xifblank{ string }{ true }{ false } +%% \xifblank{ string }{ true }{ false } \newrobustcmd\xifblank[1]{\begingroup \protected@edef\@xifblank{\endgroup \noexpand\ifblank{#1}% }\@xifblank} -% \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 +%% \deblank{ string } +\newcommand\deblank[1]{\romannumeral-`\q\ettl@deblank#1/ /} +\long\def\ettl@deblank#1 /{\ettl@deblank@i#1/} +\long\def\ettl@deblank@i#1/#2{ #1} +\newcommand\ettl@stringify[1]{\romannumeral-`\q\ettl@expandafthree\@gobblescape% + \expandafter\ettl@deblank\detokenize{#1}/ /} -% \ifstrcmp{ string1 }{ string2 }{ true }{ false } -\newcommand\ifstrcmp[2]{\csname @% +%% \ifstrcmp{ string1 }{ string2 }{ true }{ false } +\newcommand\ifstrcmp[2]{\romannumeral\csname rmn@% \ifnum\pdfstrcmp{\detokenize{#1}}{\detokenize{#2}}=0 first\else second\fi oftwo\endcsname} -\ettl@onlypdfTeX\pdfstrcmp\ifstrcmp +\ettl@onlypdfTeX\pdfstrcmp\ifstrcmp[\ifstrequal] -% \xifstrcmp{ string1 }{ string2 }{ true }{ false } +%% \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 +\ettl@onlypdfTeX\pdfstrcmp\xifstrcmp[\xifstrequal] +\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} +%% \ifcharupper{ string }{ true }{ false } +%% \ifcharlower{ string }{ true }{ false } +\newcommand\ifcharupper[1]{\romannumeral\csname rmn@% + \ifnum`\#1=\uccode`\#1 first\else second\fi oftwo\endcsname} +\newcommand\ifcharlower[1]{\romannumeral\csname rmn@% + \ifnum`\#1=\lccode`\#1 first\else second\fi oftwo\endcsname} + +%% \ifuppercase{ string }{ true }{ false } +%% \iflowercase{ string }{ true }{ false } +\newrobustcmd\ifuppercase[1]{\uppercase{\ifstrcmp{#1}}{#1}} +\newrobustcmd\iflowercase[1]{\lowercase{\ifstrcmp{#1}}{#1}} + +%% \ifstrmatch{ pattern }{ string }{ true }{ false } +\newcommand\ifstrmatch[2]{\romannumeral\csname rmn@% + \ifnum\pdfmatch{#1}{#2}=1 first\else second\fi oftwo\endcsname} \ettl@onlypdfTeX\pdfmatch\ifstrmatch + +%% \ifstrdigit{ string }{ true }{ false } +\ettl@ifdefined\pdfmatch +\newcommand\ifstrdigit[1]{\romannumeral\csname rmn@\ifnum\pdfmatch{\detokenize{^[[:digit:]]$}}% + {\detokenize{#1}}=1 first\else second\fi oftwo\endcsname} +\else +\def\do#1{\cslet{ettl@number#1}=#1% +}\docsvlist{0,1,2,3,4,5,6,7,8,9} +\newcommand\ifstrdigit[1]{\romannumeral\csname rmn@% + \ifcsname ettl@number\detokenize{#1}\endcsname first\else second\fi oftwo\endcsname} +\fi%\pdfmatch + +%% \ifstrnum{ string }{ true }{ false } +\ettl@ifdefined\pdfmatch +\newcommand\ifstrnum[1]{\romannumeral\csname rmn@\ifnum\pdfmatch + {\detokenize{^([[:space:]]*-?)*+[[:digit:]]+[[:space:]]*$}}{\detokenize{#1}}=1 % + first\else second\fi oftwo\endcsname} +\else +\newcommand\ifstrnum[1]{\romannumeral\csname rmn@\ettl@nbk#1//% + {\expandafter\ettl@numberminus\detokenize{#1}-/End§String/}{second}//oftwo\endcsname} +\long\def\ettl@numberminus#1-#2/End§String/{\ettl@nbk#2//% + {\ettl@nbk#1//{second}{\ettl@numberminus#2/End§String/}//}% + {\expandafter\expandafter\expandafter\ettl@numberspace\deblank{#1} /End§String/}//}% +\long\def\ettl@numberspace#1 #2/End§String/{\ettl@nbk#2//{second}{\ettl@ifstrnum#1/End§String/}//} +\long\def\ettl@ifstrnum#1#2/End§String/{% + \ifcsname ettl@number#1\endcsname% #1 detokenized before, ok + \ettl@nbk#2//{\ettl@ifstrnum#2/End§String/}{first}//% + \else second% + \fi} +\fi%\pdfmatch + +%% \DeclareStringFilter[\global]{ \StringFilterMacro }{ string } +\newrobustcmd\DeclareStringFilter[3][\global]{\@ifdefinable#2% + {\expandnext\ettl@declarestrfilter% + {\csname\@gobblescape#2\detokenize{->"#3"}\endcsname}{#1}{#2}{#3}}} +\newcommand\ettl@declarestrfilter[4]{% + #2\csdef{\@gobblescape#1}##1#4##2/End§String/{##1/##2}% This the FILTER + #2\long\def#3##1{\FE@modifiers{=<>?-+!}{##1} + {\ettl@strfilt@mod 0{{#4}{}{#1}[1]}}%= + {\ettl@strfilt@mod 1{{#4}{}{#1}[1]}}%< + {\ettl@strfilt@mod 2{{#4}{}{#1}[\ettl@intmax]}}%> + {\ettl@strfilt@mod 3{{#4}{}{#1}}}%? + {\ettl@strfilt@mod 4{{#4}{}{#1}}}%- + {\ettl@strfilt@mod 5{{#4}{}{#1}}}%+ + {\ettl@strfilt\ettl@strfilt@count{#4}{}{#1}[\ettl@intmax]}%! + {\ettl@strfilt\ettl@strfilt@equal{#4}{}{#1}[1]}}}% default +\long\def\ettl@ifchardot#1{\csname\ettl@BasicFilter\ettl@ifchardot@filt.#1/End§String/\endcsname} +\long\def\ettl@ifchardot@filt#1.#2/End§String/{#1/#2} +\def\ettl@strfilt@mod #1#2#3{% + \ifcase#1 \ettl@or\ettl@ifchardot{#3}% + {\ettl@strfilt\ettl@strfilt@equal#2} + {\FE@ifcharequal{#3}% + {\ettl@strfilt\ettl@strfilt@equaleq#2}% + {\ettl@strfilt\ettl@strfilt@equal#2}}% + \or\ettl@or\ettl@ifchardot{#3}% + {\ettl@strfilt\ettl@strfilt@start#2}% + {\FE@ifcharequal{#3} + {\ettl@strfilt\ettl@strfilt@starteq#2}% + {\ettl@strfilt\ettl@strfilt@start#2}}% + \or\ettl@or\ettl@ifchardot{#3}% + {\ettl@strfilt\ettl@strfilt@endby#2}% + {\FE@ifcharequal{#3} + {\ettl@strfilt\ettl@strfilt@endbyeq#2}% + {\ettl@strfilt\ettl@strfilt@endby#2}}% + \or\ettl@or\ettl@ifchardot{#3}% + {\ettl@strfilt\ettl@strfilt@instr#2[1]} + {\FE@testopt{#3}{\ettl@strfilt\ettl@strfilt@instr#2}{1}}% + \or\ettl@or\ettl@ifchardot{#3}% + {\ettl@strfilt@REMOVE{#2}[\ettl@intmax]}% + {\FE@testopt{#3}{\ettl@strfilt@REMOVE{#2}}{\ettl@intmax}}% + \or\ettl@fi\ettl@ifchardot{#3}% + {\ettl@strfilt@REPLACE#2[\ettl@intmax]}% + {\FE@testopt{#3}{\ettl@strfilt@REPLACE#2}{\ettl@intmax}}% + \fi} +\long\def\ettl@strfilt#1#2#3#4[#5]#6{% % #1 = test macro + \ExpandAftercmds#1{\ettl@Remove #6/End§String/{#2}{#3}[{#5}]{#4}}} +\long\def\ettl@strfilt@REMOVE #1[#2]{% + \ifnum\numexpr#2>0 \ettl@else\ettl@strfilt\ettl@strfilt@remove#1[#2]% + \else\expandafter\@firstofone% + \fi} +\long\def\ettl@strfilt@REPLACE #1#2#3#4[#5]#6#7{% + \ifnum\numexpr#5>0 \ettl@else\ettl@strfilt\ettl@strfilt@replace{#1}{#7}{#3}[{#5}]{#6}% + \else\expandafter\@firstoftwo% + \fi} +\long\def\ettl@Remove#1/End§String/#2#3[#4]#5{% + \expandafter\ettl@Remove@loop #5#1//#2/End§String//End§String/{#3}[{#4-1}]{#5}} +\long\def\ettl@Remove@loop#1/#2//#3/End§String/#4[#5]#6{% + \ifnum\numexpr#5>0 \ettl@nbk@else#2//% + {\ettl@Remove #1#4#2/End§String/{#3}{#4}[{#5}]{#6}} + {{#1}{#4#2}{#3}{#5}}//% + \else\ettl@fi{#1}{#4#2}{#3}{#5}% + \fi} +\long\def\ettl@strfilt@equal #1#2#3#4{\csname @% + \ettl@nbk#3//{\ettl@nbk#1#2//{second}{first}//}{second}//oftwo\endcsname} +\long\def\ettl@strfilt@equaleq #1#2#3#4{\csname @% + \ettl@nbk#3//{\ifnotempty{#1#2}{second}{first}}{second}//oftwo\endcsname} +\long\def\ettl@strfilt@start #1#2#3#4{\csname @% + \ettl@nbk#1//{second}{first}//oftwo\endcsname} +\long\def\ettl@strfilt@starteq #1#2#3#4{\csname @% + \ifnotempty{#1}{second}{first}oftwo\endcsname} +\long\def\ettl@strfilt@endby #1#2#3#4{\csname @% + \ettl@nbk#3//{first}{second}//oftwo\endcsname} +\long\def\ettl@strfilt@endbyeq #1#2#3#4{\csname @% + \ettl@nbk#3//{\ifempty{#2}{first}{second}}{second}//oftwo\endcsname} +\long\def\ettl@strfilt@count #1#2#3#4{\number\numexpr\ettl@intmax-(#4)-\ettl@nbk#3//01//} +\long\def\ettl@strfilt@instr #1#2#3#4{\csname @% + \ifnum\numexpr#4>0 second% + \else\ifnum\numexpr#4<0 first% + \else\ettl@nbk#3//{first}{second}//% + \fi\fi oftwo\endcsname} +\long\def\ettl@strfilt@remove #1#2#3#4{#1#2} +\long\def\ettl@strfilt@replace #1#2#3#4{#1\ettl@nbk#3//{#2}{}//} %---------------------------------------------------------------------------- % 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@testopt{ #1 }{ commands }{ default option } +\long\def\ettl@BasicFilter#1#2#3/End§String/{\expandafter\ettl@B@sicFilter #1#3//#2/End§String//End§String/} +\long\def\ettl@B@sicFilter#1/#2//#3/End§String/{@\ettl@nbk#3//% + {\if\relax\detokenize{#1#2}\relax first\else second\fi} + {second}//oftwo} +\newcommand\FE@testopt[3]{\csname\ettl@BasicFilter\ettl@FE@testopt[#1/End§String/\endcsname + {#2#1}% + {#2[{#3}]{#1}}}%] +\long\def\ettl@FE@testopt#1[#2/End§String/{#1/#2} -% \FE@ifstar{ #1 } { \StarredMacro }{ \NotStarredMacro } -\newcommand\FE@ifstar[3]{\ifsinglechar *{#1}{#2}{#3{#1}}} +%% \FE@ifstar{ #1 } { \StarredMacro }{ \NotStarredMacro } +\newcommand\FE@ifstar[3]{\csname\ettl@BasicFilter\ettl@FE@ifstar*#1/End§String/\endcsname + {#2}% + {#3{#1}}} +\long\def\ettl@FE@ifstar#1*#2/End§String/{#1/#2} -% \FE@ifchar{#1}{#2}{ \SpecialFormMacro }{ \NormalMacro } +%% \FE@charequal{ #1 } { \MacroWith= }{ \NormalMacro } % used by the string filters +\ettl@ifdefined\pdfmatch% use \ettl@ifdefined to test both on pdfTeX (make \ettl@ifdefined=\iffalse) +\newcommand\FE@ifcharequal[3]{\ifsinglechar ={#1}{#2}{#3{#1}}} +\else +\newcommand\FE@ifcharequal[3]{\csname\ettl@BasicFilter\ettl@FE@charequal=#1/End§String/\endcsname + {#2}% + {#3{#1}}} +\long\def\ettl@FE@charequal#1=#2/End§String/{#1/#2} +\fi + +%% \FE@ifchar{ }{ #1 }{ \SpecialFormMacro }{ \NormalMacro } \newcommand\FE@ifchar[4]{\ifsinglechar{#1}{#2}{#3}{#4{#2}}} -%% \iffalse - -% \DeclareCmdListParser : general constructor for command-list parsers -% \DeclareCmdListParser\ParserName{separator} -\newrobustcmd*\DeclareCmdListParser[2]{% - \@ifdefinable#1 - {\expandafter\etextools@defcmdparser\expandafter{#1}{#2}}} -\begingroup\catcode`\&=3\catcode`\`=3 -\gdef\etextools@defcmdparser#1#2{% - \begingroup - \def\`##1`{\expandafter\noexpand\csname ##1\endcsname}% - \protected@edef\defineparser{\endgroup - \long\def#1####1{\noexpand\FE@ifstar{####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&{% - \noexpand\ifblank{####2} - {} - {\noexpand\ettl@lst@doitem{####1}{####2}}% - \noexpand\ifblank{####3} - {\noexpand\ettl@listbreak} - {\`ettl@lst@\string#1`{####1}####3}&}% - }\defineparser}% - \long\gdef\ettl@lst@doitem#1#2{#1{#2}}% - \long\gdef\ettl@listbreak#1&{}% -\endgroup +%% \FE@modifiers{ Allowed Characters }{ #1 }{ \MacroA }{ \MacroB }{ \MacroC }...{ \MacroZ }{ \MacroDefault } +\newcommand\FE@modifiers[2]{% + \ifOneToken{#2}% + {\ExpandAftercmds\ettl@FE@modifiers% + {\ExpandAftercmds{\ettl@setresult 12of3><} + {\ettl@getsinglelist{\ettl@ifchar{#2}}{#1}}}{#2}} + {\ExpandNextTwo{\ettl@supergobble[{{#2}}]}{-1}{\getcharlistcount{#1}+1}}} +\long\def\ettl@FE@modifiers#1#2#3{\expandafter\ettl@supergobble% + \expandafter[\romannumeral-`\q\ifnum#2<0 {#3}\fi]{#2}{#1+1}} +%% \ettl@supergobble{ p }{ q }{token_1}{token_2}...{token_p}{TOKEN_p+1}{token_p+2}...{token_p+q+1} +\newcommand\ettl@supergobble[1]{\FE@testopt{#1}\ettl@superg@bble{}} +\long\def\ettl@superg@bble[#1]#2#3{% + \ifnum\numexpr#3>0 + \ifnum\numexpr#3-(#2)=0 + \ettl@supergobble@loop{#3+2}0{\ettl@supergobble@end{}{}}% + \else + \expandafter\ettl@supergobble@loop\expandafter{% + \number\numexpr\ifnum\numexpr#2*(#2-(#3))>0 #3+1\else#2+2\fi}{#3+2}% + {\ettl@supergobble@next{}{#1}}% + \fi\fi} +\long\def\ettl@supergobble@loop#1#2#3{% + \ifcsname ettl@supergobble\number\numexpr#1\endcsname + \csname ettl@supergobble\number\numexpr#1\endcsname + {#3{#2-(#1)-1}}% + \else\ettl@supergobbleheight{\ettl@supergobble@loop{#1-8}{#2-8}{#3}}% + \fi} +\long\def\ettl@supergobble@end#1#2#3{\fi\fi\fi#1#2} +\long\csdef{ettl@supergobbleheight}#1\fi#2#3#4#5#6#7#8#9{\fi#1} +\long\csdef{ettl@supergobble7}#1#2\fi#3#4#5#6#7#8#9{#1} +\long\csdef{ettl@supergobble6}#1#2\fi#3#4#5#6#7#8{#1} +\long\csdef{ettl@supergobble5}#1#2\fi#3#4#5#6#7{#1} +\long\csdef{ettl@supergobble4}#1#2\fi#3#4#5#6{#1} +\long\csdef{ettl@supergobble3}#1#2\fi#3#4#5{#1} +\long\csdef{ettl@supergobble2}#1#2\fi#3#4{#1} +\long\csdef{ettl@supergobble1}#1#2\fi#3{#1} +\long\csdef{ettl@supergobble0}#1#2\fi{#1} +\long\def\ettl@supergobble@next#1#2#3#4{\fi + \ettl@supergobble@loop{#3}0{\ettl@supergobble@end{#4}{#2}}} + +%% \AfterGroup{ code } / \AfterGroup*{ code } the star form expands its argument once +\newcount\ettl@fter +\newrobustcmd\AfterGroup{\@ifstar{\ettl@AfterGroup\@firstofone}{\ettl@AfterGroup\unexpanded}} +\newrobustcmd\ettl@AfterGroup[2]{% + \csxdef{ettl@aftergroup@hook\number\numexpr\the\ettl@fter+1}% + {\global\csundef{ettl@fterGroup\number\numexpr\the\ettl@fter+1}#1{#2}}% + \global\advance\ettl@fter\@ne + \expandafter\aftergroup\csname ettl@fterGroup\the\ettl@fter\endcsname} + +%% \AfterAssignment{ code } +\newrobustcmd\AfterAssignment{\@ifstar{\ettl@AfterAssignment\@firstofone}{\ettl@AfterAssignment\unexpanded}} +\newrobustcmd\ettl@AfterAssignment[2]{% + \csedef{ettl@afterassignment@hook\number\numexpr\the\ettl@fter}{#1{#2}}% + \global\advance\ettl@fter\@ne + \expandafter\afterassignment\csname ettl@afterassignment@hook\the\ettl@fter\endcsname} + +%% \aftergroup@def{ cs-token } +\newrobustcmd\aftergroup@def[1]{% + \let\etex@let@primitive\let \def\let{\global\etex@let@primitive}% + \expandafter\LetLtxMacro\csname ettl@ftergroup@def\number\numexpr\the\ettl@fter+1\endcsname#1% + \global\advance\ettl@fter\@ne + \etex@let@primitive\let=\etex@let@primitive + \aftergroup\LetLtxMacro \aftergroup#1% + \expandafter\aftergroup\csname ettl@ftergroup@def\the\ettl@fter\endcsname + \aftergroup\global \aftergroup\undef + \expandafter\aftergroup\csname ettl@ftergroup@def\the\ettl@fter\endcsname} +%---------------------------------------------------------------------------- + +%% \@ifchar{ single token }{ true }{ false } -% \csvloop[\command]\csvListMacro -% \csvloop*[\command]{item,item,item} +\long\def\@ifchar#1#2{\ettl@ifnextchar #1{\@firstoftwo{#2}}} + +%% \ettl@ifnextchar{ character token }{ true }{ false } + +\newrobustcmd\ettl@ifnextchar[3]{\begingroup + \edef\1##1/##2/##3{##1\endgroup\unexpanded{#2}##3}% + \edef\2##1/##2/##3{##1\endgroup\unexpanded{#3}##3}% + \ifOneToken{#1} + {\csname ettl@\if\relax\expandafter\ettl@cdr\detokenize{#1}\@nil\relax % OneChar + xifnch\else xifntk\fi\endcsname{#1}} + {\2//{}}} +\long\def\ettl@xifnch#1{% + \ifx#1\@sptoken \def\ettl@xifnch{\ifx\@let@token\@sptoken\1\else\2\fi//{}}% + \else \def\ettl@xifnch{% + \ifx\@let@token\bgroup \2 + \else\ifx\@let@token\egroup \2 + \else\ifx\@let@token\@sptoken \ettl@ifnspace\ettl@xifnch% + \else\ettl@ifnch% + \fi\fi\fi/{#1}/{}}% + \fi\futurelet\@let@token\ettl@xifnch} +\long\def\ettl@ifnch#1/#2/#3{#1\long\def\ettl@ifnch##1{\ettl@char{##1} + {\if\string##1\string#2\1\else\2\fi}\2//{##1}}\ettl@ifnch} +\long\def\ettl@xifntk#1{% + \ifx#1\bgroup\def\ettl@xifntk{\ifx\@let@token\bgroup\1\else\2\fi//{}}% + \else\ifx#1\egroup\def\ettl@xifntk{\ifx\@let@token\egroup\1\else\2\fi//{}}% + \else\def\ettl@xifntk{% + \ifx\@let@token\bgroup \2 + \else\ifx\@let@token\egroup \2 + \else\ifx\@let@token\@sptoken \ettl@ifnspace\ettl@xifntk% + \else\ettl@ifntk% + \fi\fi\fi/{#1}/{}}% + \fi\futurelet\@let@token\ettl@xifntk} +\long\def\ettl@ifntk#1/#2/#3{#1\long\def\ettl@ifntk##1{\ettl@char{##1} + \2{\ifx##1#2\1\else\2\fi}//{##1}}\ettl@ifntk} +\long\def\ettl@ifnspace#1#2/#3/#4 {#2\futurelet\@let@token#1} + +%% \futuredef[list of allowed tokens]{ command }{ commands to expand after } +%% \futuredef*[list of allowed tokens]{ command }{ commands to expand after } +%% \futuredef=[list of allowed tokens]{ command }{ commands to expand after } +%% \futuredef*=[list of allowed tokens]{ command }{ commands to expand after } (or \futuredef=*[...] ) +\newrobustcmd*\futuredef{\begingroup\ettl@futdef\ettl@futuredef\detokenize} +\protected\def\ettl@futdef#1#2{\@ifstar% + {\ettl@futdef\ettl@futurd@f#2} + {\@ifchar={\ettl@futdef#1\unexpanded} + {\@testopt{\ettl@futur@def#1#2}}}} +\long\def\ettl@futur@def#1#2[#3]{% + \csname ettl@\if\relax\detokenize{#3}\relax1\else2\fi of2\endcsname + {\let \ettl@x \@empty \letcs \ettl@futur@def@collect{\@gobblescape#1@collectall}}% + {\def \ettl@x {#3}\edef \ettl@y {#2{#3}}% + \ifx\ettl@x\ettl@y \let\ettl@y\@gobble + \else \ifx#2\unexpanded \let\ettl@y\@gobble + \else \def\ettl@y{\edef\ettl@x}% + \fi\fi\ettl@y{\detokenizeChars{#3}}% + \letcs\ettl@futur@def@collect{\@gobblescape#1@collect}}% + \expandafter#1\expandafter#2\expandafter{\ettl@x}} +\long\def\ettl@futuredef#1#2#3#4{% #1=detokenize #2=list, #3=macro result, #4=code-next + \def \ettl@futuredef@loop{\ettl@futuredef@test{}}% + \long \def \ettl@futuredef@test##1{% + \ifcat\noexpand\ettl@x\bgroup\ettl@futuredef@end{}\else + \ifcat\noexpand\ettl@x\egroup\ettl@futuredef@end{}\else + \ifcat\noexpand\ettl@x\ettl@sptoken\ettl@futuredef@space#1\else + \ettl@futur@def@collect#1\fi\fi\fi/Ne¤t/{#2}{##1}}% + \long \def \ettl@futuredef@end##1##2/Ne¤t/##3##4{##2\endgroup\def#3{##4}#4##1}% + \futurelet \ettl@x \ettl@futuredef@loop} +\long\def\ettl@futuredef@collect#1#2/Ne¤t/#3#4#5{#2% + \ifcat\noexpand#5\relax \ettl@futuredef@filt\unexpanded + \else \ettl@futuredef@filt#1 + \fi{#5}{#3} + {\def\ettl@futuredef@loop{\ettl@futuredef@test{#4#5}}\futurelet\ettl@x\ettl@futuredef@loop} + {\ettl@futuredef@end{#5}/Ne¤t/{}{#4}}/Ne¤t/} +\long\def\ettl@futuredef@space#1#2/Ne¤t/#3#4 {\ettl@futur@def@collect#1#2/Ne¤t/{#3}{#4}{ }} +\long\def\ettl@futuredef@collectall#1#2/Ne¤t/#3#4#5{#2% + \def\ettl@futuredef@loop{\ettl@futuredef@test{#4#5}}\futurelet\ettl@x\ettl@futuredef@loop} +\long\def\ettl@futur@def@filt#1#2{% #1=token to check, #2=allowed list + \long\def\ettl@futdef@filt##1#1##2##3/##4##5##6/Ne¤t/{##5}% + \ettl@futdef@filt#2#1//} +\long\def\ettl@futuredef@filt#1#2\fi#3#4{\fi % #1=detokenize/unexpanded, #2=discard, #3=token,#4=allowed list + \expandafter\ettl@futur@def@filt\expandafter{#1{#3}}{#4}} +\long\def\ettl@futured@f#1#2#3#4{\begingroup%#1=test macro,#2=list,#3=macro,#4=code-next + \let\ettl@y\@undefined + \def \ettl@futured@f@loop{\ettl@futured@f@test{}}% + \long \def \ettl@futured@f@test##1{% + \csname @\ettl@ifinsinglelist#1\ettl@x#2/End§List/oftwo\endcsname + {\ifcat\noexpand\ettl@x\bgroup\ettl@futuredef@end{##1}\fi + \ifcat\noexpand\ettl@x\egroup\ettl@futuredef@end{##1}\fi + \ifcat\noexpand\ettl@x\ettl@sptoken\ettl@futured@f@space{##1}{ }\fi + \ettl@futured@f@collect{##1}/Ne¤t/} + {\ettl@futured@f@expand{##1}}}% + \long \def \ettl@futuredef@end##1\fi##2/Ne¤t/{\fi\endgroup\def#3{##1}#4}% + \futurelet \ettl@x \ettl@futured@f@loop} +\long\def\ettl@futured@f@collect#1#2/Ne¤t/#3{% + #2\def\ettl@futured@f@loop{\ettl@futured@f@test{#1#3}}\let\ettl@y\@undefined% + \futurelet\ettl@x\ettl@futured@f@loop} +\long\def\ettl@futured@f@expand@nbk#1{% + \ifcat\noexpand\ettl@x\ettl@sptoken\ettl@futured@f@space{#1}{}\fi + \ifx\ettl@x\ettl@y\ettl@futuredef@end{#1}% + \else\let\ettl@y\ettl@x\ettl@futured@f@exp@nd\fi/Ne¤t/} +\long\def\ettl@futured@f@expand@bk#1{% + \ifcat\noexpand\ettl@x\bgroup\ettl@futuredef@end{#1}\fi + \ifcat\noexpand\ettl@x\egroup\ettl@futuredef@end{#1}\fi + \ifcat\noexpand\ettl@x\ettl@sptoken\ettl@futured@f@space{#1}{ }\fi + \ifx\ettl@x\ettl@y\ettl@futured@f@collect{#1}% + \else\let\ettl@y\ettl@x\ettl@futured@f@exp@nd% + \fi/Ne¤t/} +\long\def\ettl@futured@f@exp@nd#1/Ne¤t/{% + #1\expandafter\futurelet\expandafter\ettl@x\expandafter\ettl@futured@f@loop} +\csdef{ettl@futured@f@space}#1#2\fi#3/Ne¤t/ {% + \def\ettl@futured@f@loop{\ettl@futured@f@test{#1#2}}\let\ettl@y\@undefined + \futurelet\ettl@x\ettl@futured@f@loop} + +%---------------------------------------------------------------------------- + +%% \naturalloop [ auxiliary commands (default \do) ]{ n times }{ argument } +\newcommand\naturalloop[1]{\FE@testopt{#1}\ettl@naturalloop{\do}} +\def\ettl@naturalloop[#1]#2#3{% + \ifnum\numexpr#2>0 \ExpandNext{\ettl@naturall@@p[{#1}]{#2-1}{1}{#3}}{#1[1]{#3}{#3}}% + \else\ettl@fi#3% + \fi} +\def\ettl@naturall@@p[#1]#2#3#4#5#6\fi{\fi% + \ifnum\numexpr#2>0 \ExpandNext{\ettl@naturall@@p[{#1}]{#2-1}{#3+1}{#4}}{#1[#3+1]{#4}{#5}}% + \else\ettl@fi#5% + \fi} + +%% \ifinttokslist{ item }{ list of tokens }{ true }{ false } +\newcommand\ifintokslist[4]{\romannumeral\csname @% + \expandafter\ettl@nbk\romannumeral\ettl@dosinglelist{\ettl@ifintokslist{#1}}{#2}//{first}{second}//% + oftwo\endcsname{\z@#3}{\z@#4}} +\long\def\ettl@ifintokslist#1#2{\ettl@ifx{#1}{#2}{\expandafter\z@\ettl@breakloop}{}} +\newcommand\ifincharlist[4]{\romannumeral\csname @% + \expandafter\ettl@nbk\romannumeral\ettl@dosinglelist{\ettl@ifincharlist{#1}}{#2}\z@//{first}{second}//% + oftwo\endcsname{\z@#3}{\z@#4}} +\long\def\ettl@ifincharlist#1#2{\ettl@ifchar{#1}{#2}{\expandafter\z@\ettl@breakloop}{}} +\long\def\ettl@dosinglelist#1#2{\ettl@nbk#2//% + {\ettl@dosinglelist@loop{#1}#2//{\ettl@dosinglelist@loop{#1}}\ettl@breakloop} + \ettl@breakloop///End§List/} +\long\def\ettl@dosinglelist@loop#1#2#3#4/#5#6#7/End§List/{% + #1{#2}#6{#3}#4//{#6}#7/End§List/} + +%% \gettokslistindex { item }{ list of tokens } +%% \gettokslistcount { item }{ list of tokens } +%% \gettokslisttoken { item }{ list of tokens } +\newcommand\gettokslistindex[2]{\number\ifnotempty{#2}{\ettl@nbk#1//% + {\ExpandAftercmds{\ettl@setresult 2of3><}{\ettl@getsinglelist{\ettl@ifx{#1}}{#2}}} + {-1}//}{-1}} +\newcommand\getcharlistindex[2]{\number\ifnotempty{#2}{\ettl@nbk#1//% + {\ExpandAftercmds{\ettl@setresult 2of3><}{\ettl@getsinglelist{\ettl@ifchar{#1}}{#2}}} + {-1}//}{-1}} +\newcommand\gettokslistcount[1]{\number\ifnotempty{#1}% + {\ExpandAftercmds{\ettl@setresult 1of3><}{\ettl@getsinglelist{\ettl@ifx{\\}}{#1}}} + 0} +\newcommand\getcharlistcount[1]{}% +\let\getcharlistcount=\gettokslistcount +\newcommand\gettokslisttoken[2]{\ifnotempty{#2}{\ettl@nbk#1//% + {\ExpandAftercmds{\ettl@setresult 3of3><}{\ettl@getsinglelist{\ettl@ifx{#1}}{#2}}} + {}//}{}} +\newcommand\getcharlisttoken[2]{\ifnotempty{#2}{\ettl@nbk#1//% + {\ExpandAftercmds{\ettl@setresult 3of3><}{\ettl@getsinglelist{\ettl@ifchar{#1}}{#2}}} + {}//}{}} +\long\def\ettl@getsinglelist#1#2{\ettl@singlelist@loop{#1}{-1}{-1}{}#2//% + \ettl@singlelist@loop\ettl@singlelist@result/End§List/} +\long\def\ettl@singlelist@loop#1#2#3#4#5#6/#7#8#9/End§List/{% + \csname @#1#5{first}{second}oftwo\endcsname + {#8{#1}{#2+1}{#3+1+0*(0}{#5}#6//#8#9} + {#8{#1}{#2+1}{#3+1}{#4}#6//#8#9}/End§List/} + +\def\ettl@singlelist@result#1#2#3#4#5/End§List/{\ExpandNextTwo\@swaptwo% + {\number\numexpr\ifempty{#4}{-1}{#3)}}{\number\numexpr#2}{#4}} +\def\ettl@setresult#1of#2>#3<{\ettl@nbk #3//% + {\ifdefcount{#3}{#3=\csname ettl@#1of#2\endcsname} + {\edef#3{\csname ettl@#1of#2\endcsname}}}% + {\csname ettl@#1of#2\endcsname}//} + +%% \DeclareCmdListParser : general constructor for command-list parsers +%% \DeclareCmdListParser\ParserName{separator} +\newrobustcmd\DeclareCmdListParser[3][\global]{\@ifdefinable{#2}{\begingroup + \protected\def\ettl@defcmdparser##1{% + \edef\ettl@defcmdparser{\endgroup\ettl@defcmdparser + {#1}{\noexpand#2}{\unexpanded{#3}} + {\noexpandcs{##1->start}} + {\noexpandcs{##1->loop}} + {\noexpandcs{##1->loop+}} + {\noexpandcs{for##1}}% + }\ettl@defcmdparser + }\expandafter\ettl@defcmdparser\expandafter{\romannumeral-`\q\@gobblescape#2}}} +\protected\long\def\ettl@defcmdparser#1#2#3#4#5#6#7{%#1=global,#2=command,#3=sep,#4=start,#5=loop,#6=loop+ + #1\long\def#4##1##2[##3]##4{% ##1=case, ##2=expandafter??? , ##3=do, ##4=list + ##2{##4}% ifiscs or @thirdofthree + {\expandafter\@swaparg\expandafter{##4}{#4{##1}\@thirdofthree[{##3}]}} + {\ettl@nbk##4//% + {\ifcase##1 \ettl@or\@swaplast{#60{\ettl@lst@count}}#6% + \or \ettl@or\@swaplast{#60{\ettl@lst@getitem{##3}}}#6% + \or \ettl@or\@swaplast{#5{##3}}#5% + \or \ettl@fi\@swaplast{#60{##3}}#6% + \fi{##4#3//}\ettl@breakloop + }\ettl@breakloop///End§List/}}% + #1\long\def#5##1##2#3##3##4/##5##6##7/End§List/{% + \if\relax\detokenize{##2}\relax\expandafter\@gobbletwo\fi\@firstofone{##1{##2}}% + ##6{##1}##3##4//{##6}##7/End§List/} + #1\long\def#6##1##2##3#3##4##5/##6##7##8/End§List/{% + \if\relax\detokenize{##3}\relax\expandafter\@gobbletwo\fi\@firstofone{##2[##1]{##3}}% + \expandafter##7\expandafter{\number\numexpr##1+1}{##2}##4##5//{##7}##8/End§List/} + #1\protected\def#7{\@ifchar*% + {\@ifchar+{\ettl@forloop{\expandafter#2\expandafter*\expandafter+}{[####1]####2}} + {\ettl@forloop{\expandafter#2\expandafter*\expandafter+}{####1}}} + {\@ifchar+{\@ifchar*% + {\ettl@forloop{\expandafter#2\expandafter*\expandafter+}{[####1]####2}} + {\ettl@forloop{\expandafter#2\expandafter+}{[####1]####2}}} + {\ettl@forloop{\expandafter#2}{####1}}}} + #1\def#2{\ettl@lst@modif#423\ifiscs}} +\long\def\ettl@lst@getitem#1[#2]#3{% + \ifnum\numexpr#1<0 \expandafter\breakloop\fi + \ifnum\numexpr#1=#2 \ettl@fi#3\breakloop\fi} +\long\def\ettl@lst@count[#1]#2{+\ettl@nbk#2//10//} +\long\def\ettl@lst@modif#1#2#3#4#5{\FE@modifiers{*+![}{#5}% + {\ettl@lst@modif{#1}#2#3\@thirdofthree}% * case + {\ettl@lst@modif{#1}#3#2{#4}}% + (case 3/default 2) + {\ettl@lst@modif{\number\numexpr#1}00{#4}}% ! (case 0) + {\ettl@lst@opt{#1}{#2}{#4}#5}% [ (option) + {\ettl@lst@opt{#1}{#2}{#4}[\do]}}% (default option) +\long\def\ettl@lst@opt#1#2#3[#4]{% + \expandafter#1\expandafter{\number\ifnum#2=0 0\else\ifstrnum{#4}{1}{#2}\fi}{#3}[{#4}]} +\long\def\ettl@breakloop#1/End§List/{} +\let\breakloop\ettl@breakloop +\globcount\ettl@for@nested +\long\def\ettl@forloop#1#2#3\do{% + \global\advance\ettl@for@nested\@ne\relax + \csdef{ettl@for@loop\the\ettl@for@nested}{% + #1\expandafter[\csname ettl@for@do\the\ettl@for@nested\endcsname]{#3}% + \csundef{ettl@for@do\the\ettl@for@nested}% + \csundef{ettl@for@loop\the\ettl@for@nested}% + \global\advance\ettl@for@nested\m@ne\relax} + \expandafter\afterassignment\csname ettl@for@loop\the\ettl@for@nested\endcsname + \long\csdef{ettl@for@do\the\ettl@for@nested}#2} + + +%% \csvloop[\command]\csvListMacro +%% \csvloop*[\command]{item,item,item} \DeclareCmdListParser\csvloop{,} \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}} - -\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 \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} -%\listedel\listMacro{item} -%\listxdel\listMacro{item} -\newrobustcmd\listdel[2]{\@listdel\def{#1}{#2}}% -\newrobustcmd\listgdel[2]{\@listdel\gdef{#1}{#2}}% -\newrobustcmd\listxdel[2]{\begingroup - \protected@edef\@listxdel{\endgroup - \unexpanded{\@listdel\gdef{#1}}{#2}% - }\@listxdel}% -\newrobustcmd\listedel[2]{\begingroup - \protected@edef\@listedel{\endgroup - \unexpanded{\@listdel\def{#1}}{#2}% - }\@listedel} -\begingroup\catcode`\|=3\catcode`\&=3 -\long\gdef\@listdel#1#2#3{% -\begingroup - \long\def\@tempa##1|#3|##2&{##1|##2\@tempb}% - \long\def\@tempb|##1|\@tempb##2|\@tempb{% - \ifblank{##2}{\unexpanded{##1}} - {\ifblank{##1}{}{\@tempx##1&}}}% - \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}&}% - }\@redef}% end of \@listdel +\DeclareCmdListParser\listloop{|}% global declaration \endgroup +\DeclareCmdListParser\toksloop{} +%% \forcsvloop\csvListMacro\do{...#1...} +%% \forcsvloop*{item,item,item,...}\do{...#1...} -% \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 -\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 - {\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 - - -%\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#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&}% - \else\ifnum#2>0 \ettl@afterfifi - \expandnext\ettl@get@list@item{\ettl@list@other@item#1&}{#2-1}% - \fi\fi}} -\endgroup +%% \csvlistadd \csvListMacro { item } +%% \csvlist(g|e|x)add \csvListMacro { item } +\providerobustcmd\csvlistadd[2]{\ettl@nbk#2//{\appto#1{#2,}}{}//} +\providerobustcmd\csvlistgadd[2]{\ettl@nbk#2//{\gappto#2{#2,}}{}//} +\providerobustcmd\csvlisteadd[2]{\begingroup \protected@edef#1{#2}% + \expandafter\ettl@nbk#1//{\expandafter\endgroup + \expandafter\appto\expandafter#1\expandafter{#1,}}\endgroup//} +\providerobustcmd\csvlistxadd[2]{\begingroup \protected@edef#1{#2}% + \expandafter\ettl@nbk#1//{\expandafter\endgroup + \expandafter\gappto\expandafter#1\expandafter{#1,}}\endgroup//} +%% \csvtolist [\ListMacro] \csvListMacro +%% \csvtolist* [\ListMacro] {item,item,item} +% Recommended use: \edef\ListMacro{\csvtolist{item,item,item}} +\newcommand\csvtolist[1]{\FE@ifstar{#1}{\ettl@convertlist{{\csvloop*}\ettl@do@csvtolist}} + {\ettl@convertlist{\csvloop\ettl@do@csvtolist}}} +\long\def\ettl@convertlist#1#2{\FE@testopt{#2}{\ettl@convert@list#1}{}} +\long\def\ettl@convert@list#1#2[#3]#4{\ettl@nbk#3//% + {\edef#3{#1[#2]{#4}}} + {#1[#2]{#4}}//} +\begingroup\catcode`\|=3% etb catcode +\long\gdef\ettl@do@csvtolist#1{\unexpanded{#1}|} +\endgroup -% \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}} +%% \listtocsv [\csvListMacro] \ListMacro +%% \listtocsv* [\csvListMacro] { expanded List } +% Recommended use: \edef\csvListMacro{\listtocsv\ListMacro} +\newcommand\listtocsv[1]{\FE@ifstar{#1}{\ettl@convertlist{{\listloop*}\ettl@do@listtocsv}} + {\ettl@convertlist{\listloop\ettl@do@listtocsv}}} +\long\def\ettl@do@listtocsv#1{\unexpanded{#1,}} +%% \tokstolist [\ListMacro] { \toksListMacro / token token token } +\newcommand\tokstolist[1]{\FE@ifstar{#1}{\ettl@convertlist{{\toksloop*}\ettl@do@tokstolist}} + {\ettl@convertlist{\toksloop\ettl@do@tokstolist}}} +\begingroup\catcode`\|=3% etb catcode +\long\gdef\ettl@do@tokstolist#1{\unexpanded{#1}|} \endgroup +%% \csvtolistadd \ListMacro \csvListMacro +%% \csvtolistadd* \ListMacro {item,item,item} +\newrobustcmd*\csvtolistadd{\@ifstar{\ettl@csvtolistadd*}{\ettl@csvtolistadd{}}} +\long\def\ettl@csvtolistadd#1#2#3{\eappto#2{\csvtolist#1[]{#3}}} + +%% \tokstolistadd \ListMacro { \toksListMacro / token token token } +\newrobustcmd*\tokstolistadd{\@ifstar{\ettl@tokstolistadd*}{\ettl@tokstolistadd{}}} +\long\def\ettl@tokstolistadd#1#2#3{\eappto#2{\tokstolist#1[]{#3}}} +\newrobustcmd\ettl@RemoveInList[2]{\begingroup + \def\ettl@RemoveInList##1{% + \edef\ettl@RemoveInList####1####2{% + \ettl@Rem@veInList{####1}####2\noexpandcs{##1->remove}\noexpandcs{##1->result}% + }\ettl@RemoveInList{#1}#2% + }\expandafter\ettl@RemoveInList\expandafter{\romannumeral0\@gobblescape#2}} +\protected\long\def\ettl@Rem@veInList#1#2#3#4#5#6#7#8{% + \long\def#3[##1]##2#5#8#5##3##4/##5##6##7/End§List/{##6[##1+1]##2#5##3##4//##6##7/End§List/}% + \ifnotempty{#5}%% special case if no separator + {\long\def#4[##1]#5##2#5#5##3//##4/End§List/{\unexpanded{#1\def#7{##2#5}}% + \ettl@nbk#6//\ettl@setresult 1of1>#6<{\number\numexpr##1-1\relax}{}//}}% + {\long\def#4[##1]##2//##3/End§List/{\unexpanded{#1\def#7{##2}}% + \ettl@nbk#6//\ettl@setresult 1of1>#6<{\number\numexpr##1-1\relax}{}//}}% + \long\def#2##1{#3[0]#5##1#5#5#8#5//#3#4/End§List/}% + \edef#7{\endgroup\expandafter#2\expandafter{#7}}#7} +\def\ettl@gobble@relax#1\relax{} + +%% \listdel \listMacro { item } +%% \listgdel \listMacro { item } +%% \listedel \listMacro { item } +%% \listxdel \listMacro { item } +\begingroup\catcode`\|=3 +\newrobustcmd\listdel[1][]{\ettl@RemoveInList{}\listdel|{#1}} +\newrobustcmd\listgdel[1][]{\ettl@RemoveInList\global\listdel|{#1}} +\newrobustcmd\listedel[1][]{\ettl@listedel{}\listdel|{#1}} +\newrobustcmd\listxdel[1][]{\ettl@listedel\global\listdel|{#1}} +\aftergroup@def\listdel +\aftergroup@def\listgdel +\aftergroup@def\listedel +\aftergroup@def\listxdel +\endgroup% \catcode group +\newrobustcmd\ettl@listedel[6]{\begingroup\protected@edef#5{#6}\expandafter\endgroup + \expandafter\@swaparg\expandafter{#5}{\ettl@RemoveInList#1#2{#3}{#4}#5}} + +%% \csvdel \listMacro { item } +%% \csvgdel \listMacro { item } +%% \csvedel \listMacro { item } +%% \csvxdel \listMacro { item } +\newrobustcmd\csvdel[1][]{\ettl@RemoveInList{}\csvdel,{#1}} +\newrobustcmd\csvgdel[1][]{\ettl@RemoveInList\global\csvdel,{#1}} +\newrobustcmd\csvedel[1][]{\ettl@listedel{}\csvdel,{#1}} +\newrobustcmd\csvxdel[1][]{\ettl@listedel\global\csvdel,{#1}} + +%% \toksdel \listMacro { item } +%% \toksgdel \listMacro { item } +%% \toksedel \listMacro { item } +%% \toksxdel \listMacro { item } +\newrobustcmd\toksdel[1][]{\ettl@RemoveInList{}\toksdel{}{#1}} +\newrobustcmd\toksgdel[1][]{\ettl@RemoveInList\global\toksdel{}{#1}} +\newrobustcmd\toksedel[1][]{\ettl@listedel{}\toksdel{}{#1}} +\newrobustcmd\toksxdel[1][]{\ettl@listedel\global\toksdel{}{#1}} + + +%% \getlistindex[\indexmacro]{ \Listmacro } +%% \getlistindex*[\indexmacro]{ expanded List } +\newrobustcmd\ettl@getlistindex[6][]{% #1=result, #2=\expandafter, #3=loop macro, #4=separator, #5=list of list macro, #6=item + \begingroup\def\ettl@getlistindex##1#4#6#4##2/End§List/{\endgroup + \romannumeral-`\q\ettl@setresult 1of1>#1<{\ettl@nbk##2//{#3*!{##1}}{-1}//}% + }#2\ettl@getlistindex#2#5#4#6#4/End§List/} +\begingroup\catcode`\|=3% etb catcode +\newrobustcmd\getlistindex[3][]{\@ifstar% + {\ettl@getlistindex{}\listloop{|}{#1}{#2}{#3}} + {\ifiscs{#1}{\ettl@getlistindex\expandafter\listloop|{#1}{#2}{#3}} + {\ettl@getlistindex{}\listloop|{#1}{#2}{#3}}}} +\aftergroup@def\getlistindex +\endgroup%\catcode group + +%\getcsvlistindex [\result]{ item }{ csvlistmacro } +%\getcsvlistindex*[\result]{ item }{ item,item,item } +\newrobustcmd\getcsvlistindex[3][]{\@ifstar% + {\ettl@getlistindex{}\csvloop{,}{#1}{#2}} + {\ifiscs{#1}{\ettl@getlistindex\expandafter\csvloop,{#1}{#2}} + {\ettl@getlistindex{}\csvloop,{#1}{#2}}}} +\def\ettl@if@inlist#1#2{%#1=macro,#2=separator +\newrobustcmd*#1{\@ifstar{\ettl@ifinlist{#2}{}}{\ettl@ifinlist{#2}\expandafter}}} +\def\ettl@xif@inlist#1#2{% +\newrobustcmd*#1{\@ifstar{\ettl@xifinlist{#2}{}}{\ettl@xifinlist{#2}\expandafter}}} +\protected\long\def\ettl@ifinlist#1#2#3#4{\begingroup + \def\ettl@tempa##1#1##2#1/End§List/{\endgroup\ifnotblank{##2}% + }#2\ettl@tempa#2#1#3#1#4#1/End§List/} +\protected\long\def\ettl@xifinlist#1#2#3#4{\begingroup + \protected@edef\ettl@tempa{\endgroup\ettl@ifinlist{#1}{#2}{#3}{#4}% + }\ettl@tempa} -% \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} +%% \ifincsvlist{ item }{ csvlistmacro }{ true }{ false } +%% \ifincsvlist*{ item }{ item,item,item,... }{ true }{ false } +%% \xifincsvlist{ item }{ csvlistmacro }{ true }{ false } +%% \xifincsvlist*{ item }{ item,item,item,... }{ true }{ false } +\ettl@if@inlist\ifincsvlist{,} +\ettl@xif@inlist\xifincsvlist{,} +\undef\ettl@if@inlist +\undef\ettl@xif@inlist +\DeclareOption{etoolbox}{% +\renewcommand\ifblank[3]{\ettl@nbk #1//{#2}{#3}//} +\renewcommand\ifdef[1]{\csname @\ifdefined#1first\else second\fi oftwo\endcsname} +\renewcommand\ifcsdef[1]{\csname @\ifcsname#1\endcsname first\else second\fi oftwo\endcsname} +\renewcommand\ifundef[1]{\csname @% + \ifdefined#1\ifx#1\relax first\else second\fi\else first\fi oftwo\endcsname} +\renewcommand\ifcsundef[1]{\csname @% + \ifcsname#1\endcsname\expandafter\ifx\csname#1\endcsname\relax + first\else second\fi\else first\fi oftwo\endcsname} +\edef\ifdefmacro#1{\unexpanded{\csname @% + \expandafter\ettl@ifdefmacro\meaning}#1\detokenize{macro:}/oftwo\endcsname} +\edef\ettl@ifdefmacro{% + \def\noexpand\ettl@ifdefmacro##1\detokenize{macro:}##2/{\noexpand\ettl@nbk##2//{first}{second}//}% +}\ettl@ifdefmacro +\long\edef\ifcsmacro#1{\unexpanded{\csname @% + \expandafter\expandafter\expandafter\ettl@ifdefmacro\meaningcs}{#1}\detokenize{macro:}/oftwo\endcsname} +\renewcommand\ifdefparam[1]{\csname @% + \ettl@expandaftwo\ettl@nbk\expandafter\ettl@params@meaning\meaning#1///{first}{second}//oftwo\endcsname} +\renewcommand\ifcsparam[1]{\csname @% + \expandafter\expandafter\expandafter\ettl@nbk\parameters@meaningcs{#1}//{first}{second}//oftwo\endcsname} +\renewcommand\ifnumcomp[3]{\csname @% + \ifnum\numexpr#1#2\numexpr#3 first\else second\fi oftwo\endcsname} +}% etoolbox option +\ProcessOptions \endinput -- cgit v1.2.3