%% %% This is file `etextools.sty', %% generated with the docstrip utility. %% %% The original source files were: %% %% etextools.dtx (with options: `package') %% %% This is a generated file. %% %% Copyright (C) 2009 by Florent Chervet %% %% This work may be distributed and/or modified under the %% conditions of the LaTeX Project Public License, either %% version 1.3 of this license or (at your option) any later %% version. The latest version of this license is in %% http://www.latex-project.org/lppl.txt %% %% This work consists of the main source file etextools.dtx %% and the derived files %% etextools.sty, etextools.pdf, etextools.ins, %% and etextools-examples.tex %% %%% etextools : e-TeX tools for LaTeX Users and package Writers (v.3.1 - 2009/09/30) \NeedsTeXFormat{LaTeX2e}[1996/12/01] \ProvidesPackage{etextools} [2009/09/30 v3.1 e-TeX more useful tools for LaTeX package writers] \csname ettl@onlyonce\endcsname\let\ettl@onlyonce\endinput \RequirePackage{etex,etoolbox,letltxmacro} \let\ettl@AtEnd\@empty \def\TMP@EnsureCode#1#2{% \edef\ettl@AtEnd{% \ettl@AtEnd \catcode#1 \the\catcode#1\relax }% \catcode#1 #2\relax } \TMP@EnsureCode{32}{10}% space... just in case \TMP@EnsureCode{47}{8}% / \TMP@EnsureCode{167}{7}% § \TMP@EnsureCode{164}{7}% ¤ \TMP@EnsureCode{95}{11}% _ \TMP@EnsureCode{42}{12}% * \TMP@EnsureCode{43}{12}% + \TMP@EnsureCode{45}{12}% - \TMP@EnsureCode{46}{12}% . \TMP@EnsureCode{60}{12}% < \TMP@EnsureCode{61}{12}% = \TMP@EnsureCode{62}{12}% > \TMP@EnsureCode{33}{12}% ! \TMP@EnsureCode{152}{13}% ~ for the character test \ifundef\pdfstrcmp{% \TMP@EnsureCode{163}{9}% £ ignore \TMP@EnsureCode{128}{14}% \texteuro comment € }{\TMP@EnsureCode{163}{14}% £ comment \TMP@EnsureCode{128}{9}% \texteuro ignore } \AtEndOfPackage{\ettl@AtEnd\undef\ettl@AtEnd} % A few helper macros \let\ettl@ifdefined\ifdefined%\ifdefined% turn to \iffalse to test other implementation on pdfTeX \long\def\ettl@fi#1\fi{\fi#1} \long\def\ettl@else#1\else#2\fi{\fi#1} \long\def\ettl@or#1\or#2\fi{\fi#1} \def\ettl@expandaftwo{\expandafter\expandafter\expandafter} \def\ettl@expandafthree{\expandafter\expandafter\expandafter% \expandafter\expandafter\expandafter\expandafter} \cslet{ettl@1of1}\@firstofone %% for internal use only \cslet{ettl@1of2}\@firstoftwo %% for internal use only \cslet{ettl@2of2}\@secondoftwo %% for internal use only \long\def\rmn@firstoftwo#1#2{\z@#1} %% for romannumeral \long\def\rmn@secondoftwo#1#2{\z@#2}%% for romannumeral \long\def\ettl@cdr#1#2\@nil{#2} %% \@cdr should be a LONG macro \long\def\ettl@car#1#2\@nil{#1} %% \@car should be a LONG macro \long\csdef{ettl@1of3}#1#2#3{#1} \long\csdef{ettl@2of3}#1#2#3{#2} \long\csdef{ettl@3of3}#1#2#3{#3} \long\csdef{ettl@12of3}#1#2#3{{#1}{#2}} \long\def\ettl@carcar#1#2#3#4{#4} \long\def\ettl@firstspace#1#2#3{\expandafter\ettl@firstsp@ce\detokenize{#1} \\{#3}{#2}//} \long\def\ettl@firstsp@ce#1 #2\\{\ettl@nbk#1//} \long\def\ettl@csname#1\endcsname{\fi\endcsname}%% useful to get out of \if \long\def\ettl@char#1{\csname ettl@\if @\expandafter\ettl@cdr\detokenize{#1}\@nil @% 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 @\detokenize{#1}@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} %% \@gobblescape \cs-token \newcommand*\@gobblescape{\romannumeral-`\q\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\expandaftercmds{#1} {\expandafter@cmds{#3}{\expandafter#2#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]{% \ifsingletoken\expandnext{#1} {\@expandnext{#2}{\expandafter\expandafter\expandafter}} {\expandafter\@swaparg\expandafter{#2}{#1}}} \long\def\@expandnext#1#2#3{% \ifsingletoken\expandnext{#1} {\@expandnext{#3}{\expandafter#2#2}} {#2\@swaparg#2{#3}{#1}}} %% \expandnexttwo{ code }{ control sequences }{ control sequences } \newcommand\expandnexttwo[3]{\expandnext{\expandnext{#1}{#2}}{#3}} %% \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} %% \thefontname \newcommand\thefontname{{\expandafter\ettl@thefontname\expandafter\strip@meaning\the\font}} \font\ettl@thefontname=ecrm1000 %% \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{\csname ettl@\ifx#1#21\else2\fi of2\endcsname} \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 @\detokenize{#1#2}@first\else\ifx#1#2first\else second\fi\fi}//} {\if @\detokenize\expandafter{\ettl@cdr#2\@nil}@% \expandafter\ettl@ifxsingle \else\expandafter\ettl@carcar \fi{#1}{#2}{first}{second}}% oftwo\endcsname} \def\ettl@ifxsingle#1#2#3#4{\ettl@nbk#1//{\ifx#1#2#3\else#4\fi}{#4}//} %% \ifOneToken{ token }{ true }{ false } \newcommand\ifOneToken[1]{\romannumeral\csname rmn@\ettl@firstspace{#1} {\ettl@nbk#1//{second}{\if @\detokenize{#1}@second\else first\fi}//} {\if @\detokenize\expandafter{\ettl@cdr#1\@nil}@% first\else second\fi}oftwo\endcsname} %% \ifsinglechar character{ string }{ true }{ false } \long\def\ifsinglechar#1#2{\romannumeral\csname rmn@\ettl@firstspace{#2} {\ettl@nbk#2//{second}{\if @\detokenize{#1#2}@first\else\ifx#1#2first\else second\fi\fi}//} {\if @\detokenize\expandafter{\ettl@cdr#2\@nil}@% \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 @\detokenize{#1}@second\else first\fi}//} {\if @\expandafter\ettl@cdr\detokenize{#1}\@nil @% 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 @\detokenize{#1}@secondoftwo\ettl@csname\fi \ettl@firstspace{#2}{first}{second}}//}% {\ettl@nbk#1//% {\if @\detokenize{#2}@secondoftwo\ettl@csname\fi \ettl@firstspace{#1}{first}{second}} {\if @\detokenize{#1#2}@first\else second\fi}}//% oftwo\endcsname} %% \ifiscs { string }{ true }{ false } \newcommand\ifiscs[1]{\romannumeral\csname rmn@\ettl@nbk#1//% {\if @\expandafter\ettl@cdr\detokenize{#1}\@nil @secondoftwo\ettl@csname\fi \if @\detokenize\expandafter{\ettl@cdr#1\@nil}@% \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{\romannumeral\protectspace{\z@#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 @\detokenize{#1}@% first\else second\fi oftwo\endcsname} %% \ifnotempty{ text }{ true }{ false } \newcommand\ifnotempty[1]{\romannumeral\csname rmn@\if @\detokenize{#1}@% second\else first\fi oftwo\endcsname} %% \xifempty{ text }{ true }{ false } \newcommand\xifempty[1]{\xifstrcmp{#1}{}} \ettl@onlypdfTeX\pdfstrcmp\xifempty[\xifstrempty] %% \ifnotblank{ text }{ true }{ false } \long\def\ifnotblank#1#2#3{\ettl@nbk#1//{#2}{#3}//} %% \xifblank{ string }{ true }{ false } \newrobustcmd\xifblank[1]{\begingroup \protected@edef\@xifblank{\endgroup \noexpand\ifblank{#1}% }\@xifblank} %% \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]{\romannumeral\csname rmn@% \ifnum\pdfstrcmp{\detokenize{#1}}{\detokenize{#2}}=0 first\else second\fi oftwo\endcsname} \ettl@onlypdfTeX\pdfstrcmp\ifstrcmp[\ifstrequal] %% \xifstrcmp{ string1 }{ string2 }{ true }{ false } \newcommand\xifstrcmp[2]{\csname @% \ifnum\pdfstrcmp{#1}{#2}=0 first\else second\fi oftwo\endcsname} \ettl@onlypdfTeX\pdfstrcmp\xifstrcmp[\xifstrequal] \newrobustcmd\xifstrequal[2]{\begingroup \protected@edef\@xifstrequal{\endgroup\noexpand\ifstrequal{#1}{#2}% }\@xifstrequal} %% \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 \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 } \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 @\detokenize{#1#2}@first\else second\fi} {second}//oftwo} \newcommand\FE@testopt[3]{\ettl@FE@testopt#1/[/% {#2#1}% {#2[{#3}]{#1}}}%] \long\def\ettl@FE@testopt#1[#2/#3#{\csname @\if @\detokenize{#1#2}@% first\else second\fi oftwo\endcsname} %% \FE@ifstar{ #1 } { \StarredMacro }{ \NotStarredMacro } \newcommand\FE@ifstar[3]{\ettl@FE@ifstar#1/*/% {#2}% {#3{#1}}} \long\def\ettl@FE@ifstar#1*#2/#3#{\csname @\if @\detokenize{#1#2}@% first\else second\fi oftwo\endcsname} %% \FE@charequal{ #1 } { \MacroWith= }{ \NormalMacro } % used by the string filters \newcommand\FE@ifcharequal[3]{\ettl@FE@charequal#1/=/% {#2}% {#3{#1}}} \long\def\ettl@FE@charequal#1=#2/#3#{\csname @\if @\detokenize{#1#2}@% first\else second\fi oftwo\endcsname} %% \ettl@strfilt@dot{ #1 } { \MacroWith= }{ \NormalMacro } % used by the string filters \newcommand\ettl@ifchardot[1]{\ettl@FE@chardot#1/./} \long\def\ettl@FE@chardot#1.#2/#3#{\csname @\if @\detokenize{#1#2}@% first\else second\fi oftwo\endcsname} %% \FE@ifchar{ }{ #1 }{ \SpecialFormMacro }{ \NormalMacro } \newcommand\FE@ifchar[4]{\ifsinglechar{#1}{#2}{#3}{#4{#2}}} %% \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} \let\ettl@aftergroup@def\aftergroup@def %---------------------------------------------------------------------------- %% \@ifchar{ single token }{ true }{ false } \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 @\expandafter\ettl@cdr\detokenize{#1}\@nil @% 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@futured@f#2} {\@ifchar={\ettl@futdef#1\unexpanded} {\@testopt{\ettl@futur@def#1#2}{}}}} \long\def\ettl@futur@def#1#2[#3]{% \csname ettl@\if @\detokenize{#3}@1\else2\fi of2\endcsname {\let \ettl@x \@empty \letcs \ettl@futur@def@collect{\@gobblescape#1@collectall}}% {\def \ettl@x {#3}\edef \ettl@y {#2{#3}}% \ifx\ettl@x\ettl@y \let\ettl@y\@gobble \else \ifx#2\unexpanded \let\ettl@y\@gobble \else \def\ettl@y{\edef\ettl@x}% \fi\fi\ettl@y{\detokenizeChars{#3}}% \letcs\ettl@futur@def@collect{\@gobblescape#1@collect}}% \expandafter#1\expandafter#2\expandafter{\ettl@x}} \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{% #1=detokenize #2=list, #3=macro result, #4=code-next \let \ettl@y \@undefined \def \ettl@futured@f@loop{\ettl@futured@f@test{}}% \long \def \ettl@futured@f@test##1{% \ifcat\noexpand\ettl@x\bgroup\ettl@futured@f@end\else \ifcat\noexpand\ettl@x\egroup\ettl@futured@f@end\else \ifcat\noexpand\ettl@x\ettl@sptoken\ettl@futured@f@space#1\else \ettl@futur@def@collect#1\fi\fi\fi/Ne¤t/{##1}{#2}{}}% \long \def \ettl@futured@f@end##1/Ne¤t/##2##3##4{##1\endgroup\def#3{##2}#4##4}% \futurelet \ettl@x \ettl@futured@f@loop} \long\def\ettl@futured@f@space#1#2/Ne¤t/#3#4#5 {% \ettl@futur@def@collect#1#2/Ne¤t/{#3}{#4}{#5}{ }} \long\def\ettl@futured@f@collect#1#2/Ne¤t/#3#4#5#6{#2% \ifcat\noexpand\ettl@x\relax \ettl@futuredef@filt\unexpanded \else \ettl@futuredef@filt#1 \fi{#6}{#4} {\let \ettl@y \@undefined \ettl@futured@f@append/Ne¤t/{#3}{}{#6}}% {\ettl@futured@f@try@expand{#3}\ettl@futured@f@end{#6}}/Ne¤t/} \long\def\ettl@futured@f@collectall#1#2/Ne¤t/#3#4#5#6{#2% \ettl@futured@f@try@expand{#3}\ettl@futured@f@append{#6}} \long\def\ettl@futured@f@space#1#2/Ne¤t/#3#4#5 {% \ettl@futur@def@collect#1#2/Ne¤t/{#3}{#4}{#5}{ }} \long\def\ettl@futured@f@try@expand#1#2#3{% \expandafter\ifx\noexpand\ettl@x\ettl@x \let\ettl@y=#2% \else\ettl@futured@f@CheckSpecials{#3}% {\let \ettl@y=#2}% {\ifx\ettl@x\ettl@y \let \ettl@y \ettl@futured@f@end\else \let \ettl@y \ettl@futured@f@expand\fi}% \fi\ettl@y/Ne¤t/{#1}{}{#3}} \long\def\ettl@futured@f@expand/Ne¤t/#1#2#3{\let\ettl@y\ettl@x \expandafter\futurelet\expandafter\ettl@x\expandafter\ettl@futured@f@loop#3} \long\def\ettl@futured@f@CheckSpecials#1{\ifintokslist{#1}{% \@undefined\if\ifcat\ifnum\ifdim\ifodd% \ifvmode\ifhmode\ifmmode\ifinner\ifvoid\ifhbox\ifvbox% \ifx\ifeof\iftrue\iffalse\ifcase\ifdefined\ifcsname\iffontchar% \else\fi\or}} \def\ettl@futured@f@append/Ne¤t/#1#2#3{% \def\ettl@futured@f@loop{\ettl@futured@f@test{#1#3}}% \futurelet\ettl@x\ettl@futured@f@loop}% %---------------------------------------------------------------------------- %% \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 \expandafter\@swaparg\expandafter{\romannumeral-`\q#1[0]{#3}{#3}}% {\ettl@naturall@@p[{#1}]{#2-1}{0}{#3}} \else\@swap{\unexpanded{#3}}% \fi} \def\ettl@naturall@@p[#1]#2#3#4#5#6\fi{\fi% \ifnum\numexpr#2>0 \expandafter\@swaparg\expandafter{\romannumeral-`\q% \expandafter\@swap\expandafter{\expandafter[\number\numexpr#3+1]}{#1}{#4}{#5}}% {\ettl@naturall@@p[{#1}]{#2-1}{#3+1}{#4}}% \else\@swap{\unexpanded{#5}}% \fi} %% \ifinttokslist{ item }{ list of tokens }{ true }{ false } \newcommand\ifintokslist[2]{\romannumeral\csname rmn@% \expandafter\ettl@nbk\romannumeral\ettl@dosinglelist{\ettl@ifintokslist{#1}}{#2}\z@//% {first}{second}//oftwo\endcsname} \long\def\ettl@ifintokslist#1#2{\ifx#1#2\ettl@breakloop\z@\fi} \newcommand\ifincharlist[2]{\romannumeral\csname rmn@% \expandafter\ettl@nbk\romannumeral\ettl@dosinglelist{\ettl@ifincharlist{#1}}{#2}\z@//% {first}{second}//oftwo\endcsname} \long\def\ettl@ifincharlist#1#2{\ettl@ifchar{#1}{#2}{\ettl@breakloop\z@}{}} \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}{}#2//% {\ettl@expandafthree\ettl@singlelist@loop#1}% {\expandafter\ettl@singlelist@result\@thirdofthree}/End§List/} \long\def\ettl@singlelist@loop#1#2#3#4#5/#6#7#8/End§List/{% #7{#4} {{#1+1}{#2+1+0*(0}{#4}} {{#1+1}{#2+1}{#3}}#5//{#7}{#8}/End§List/} % \csname @#1#5{first}{second}oftwo\endcsname % {#8{#1}{#2+1}{#3+1+0*(0}{#5}#6//#8#9} % {#8{#1}{#2+1}{#3+1}{#4}#6//#8#9}/End§List/} \def\ettl@singlelist@result#1#2#3#4/End§List/{\ExpandNextTwo\@swaptwo% {\number\numexpr\ifempty{#3}{-1}{#2)}}{\number\numexpr#1}{#3}} \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{\number\numexpr#60{\ettl@lst@count}}#6% \or \ettl@or\@swaplast{#60{\ettl@lst@getitem{##3}}}#6% \or \ettl@or\@swaplast{#5{##3}}#5% \or \ettl@fi\@swaplast{#60{##3}}#6% \fi{##4#3//}{\ettl@breakloop{}}% }{\ettl@breakloop{}}///End§List/}}% #1\long\def#5##1##2#3##3##4/##5##6##7/End§List/{% \if @\detokenize{##2}@\expandafter\@gobbletwo\fi\@firstofone{##1{##2}}% ##6{##1}##3##4//{##6}{##7}/End§List/} #1\long\def#6##1##2##3#3##4##5/##6##7##8/End§List/{% \if @\detokenize{##3}@\expandafter\@gobbletwo\fi\@firstofone{##2[##1]{##3}}% \expandafter##7\expandafter{\number\numexpr##1+1}{##2}##4##5//{##7}{##8}/End§List/} #1\protected\def#7{\@ifchar*% {\@ifchar+{\ettl@forloop{\expandafter#2\expandafter*\expandafter+}{[####1]####2}} {\ettl@forloop{\expandafter#2\expandafter*\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 \@swap{\breakloop{}}\fi \ifnum\numexpr#1=#2 \@swap{\breakloop{#3}}\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{#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#2/End§List/{#1} \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 \DeclareCmdListParser\listloop{|}% global declaration \endgroup \DeclareCmdListParser\toksloop{} %% \forcsvloop\csvListMacro\do{...#1...} %% \forcsvloop*{item,item,item,...}\do{...#1...} %% \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 %% \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{\romannumeral-`\q\@gobblescape#2}} \protected\long\def\ettl@Rem@veInList#1#2#3#4#5#6#7#8{% \long\def#3[##1]##2#5#8#5##3##4/##5##6##7/End§List/{##6[##1+1]##2#5##3##4//##6##7/End§List/}% \ifnotempty{#5}%% special case if no separator {\long\def#4[##1]#5##2#5#5##3//##4/End§List/{\unexpanded{#1\def#7{##2#5}}% \ettl@nbk#6//\ettl@setresult 1of1>#6<{\number\numexpr##1-1\relax}{}//}}% {\long\def#4[##1]##2//##3/End§List/{\unexpanded{#1\def#7{##2}}% \ettl@nbk#6//\ettl@setresult 1of1>#6<{\number\numexpr##1-1\relax}{}//}}% \long\def#2##1{#3[0]#5##1#5#5#8#5//#3#4/End§List/}% \edef#7{\endgroup\expandafter#2\expandafter{#7}}#7} \def\ettl@gobble@relax#1\relax{} %% \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} %% \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 %% \interval{ number }{ sorted comma separated list of numbers } \newcommand\interval[2]{\romannumeral-`\q% \ExpandNext{\avoidvoid[\csvloop!{#2}]}{\csvloop+[\ettl@do@interval{#1}]{#2}}} \def\ettl@do@interval#1[#2]#3{\ifdim#1\p@<#3\p@ \@swap{\breakloop{#2}}\fi} %% \interplin{ number }{ sorted comma separated list of numbers }{ comma separated liist of numbers } \newcommand\locinterplin[3]{\romannumeral-`\q \unless\ifnum\numexpr(\csvloop!{#2})-(\csvloop!{#3})=0 \PackageError{etextools}{Using \string\locinterplin\space the lists in argument 1 and 2\MessageBreak must have the same number of elements} {You're in trouble here and I cannot proceed...} \fi \ExpandNextTwo{\ettl@locinterplin{#1}{#3}{#2}}{\interval{#1}{#2}}{\csvloop!{#2}}} \begingroup\catcode`\/ 12% \gdef\ettl@locinterplin#1#2#3#4#5{% \ifnum#4=0 \csvloop[#4]{#2}% \else\ifnum#4=#5 \expandafter\csvloop\expandafter[\number\numexpr#5-1]{#2}% \else\ifdim#1\p@=\expandafter\csvloop\expandafter[\number\numexpr#4-1]{#3}\p@ \expandafter\csvloop\expandafter[\number\numexpr#4-1]{#2}% \else\strip@pt\dimexpr% \expandafter\csvloop\expandafter[\number\numexpr#4-1]{#2}\p@+% (#1\p@-\expandafter\csvloop\expandafter[\number\numexpr#4-1]{#3}\p@)*% (\expandafter\csvloop\expandafter[\number\numexpr#4-1]{#2}-\csvloop[#4]{#2})/% (\expandafter\csvloop\expandafter[\number\numexpr#4-1]{#3}-\csvloop[#4]{#3})\relax \fi\fi\fi} \endgroup% catcode group \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 %% %% End of file `etextools.sty'.