%% %% 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. %% %% 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 %% \NeedsTeXFormat{LaTeX2e}[1996/12/01] \ProvidesPackage{etextools} [2010/12/07 v3.1415926 e-TeX more useful tools for LaTeX package writers] \csname ettl@onlyonce\endcsname\let\ettl@onlyonce\endinput \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}% ^^a7 \TMP@EnsureCode{164}{7}% ^^a4 \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}% ^^a3 ignore \TMP@EnsureCode{128}{14}% \texteuro comment ^^80 }{\TMP@EnsureCode{163}{14}% ^^a3 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@\ifcat $\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 @% \ifcat $\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 } \providecommand*\noexpandcs[1]{\expandafter\noexpand\csname #1\endcsname} % noexpandafter \newcommand*\noexpandafter{\noexpand\expandafter} %% \thefontname \newcommand\thefontname{\nfss@text{\expandafter\expandafter\expandafter\ettl@thefontname \expandafter\expandafter\expandafter\meaning \expandafter\the\expandafter\font \expandafter\string\expandafter(% \expandafter\string\the\font\string)}} \ifcsname T1/cmr/m/n/10\endcsname \letcs\ettl@thefontname{T1/cmr/m/n/10}% \else \font\ettl@thefontname=ecrm1000 \fi %% \showcs { csname } \providecommand*\showcs[1]{\expandafter\show\csname#1\endcsname} %% \showthecs { csname } \providecommand*\showthecs[1]{\expandafter\showthe\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^^a7Meaning/{\ettl@nbk##2//\rmn@firstoftwo\rmn@secondoftwo//} \csedef{ifdef#2}##1{\noexpand\romannumeral\noexpandafter% \noexpandcs{ettl@ifdef#2}\noexpand\meaning##1#1/End^^a7Meaning/}%//{##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]{\romannumeral\csname rmn@\ettl@firstspace{#2} {\ettl@nbk#1#2//{second}{\ifcat $\detokenize{#1#2}$first\else\ifx#1#2first\else second\fi\fi}//} {\ifcat $\detokenize\expandafter{\ettl@cdr#2\@nil}$% \expandafter\ettl@ifxsingle \else\expandafter\ettl@carcar \fi{#1}{#2}{first}{second}}% oftwo\endcsname} \def\ettl@ifxsingle#1#2#3#4{\ettl@nbk#1//{\ifx#1#2#3\else#4\fi}{#4}//} %% \iffirsttoken token { string }{ true }{ false } \providecommand\iffirsttoken[2]{\romannumeral\csname rmn@% \ettl@nbk#2//% {\ettl@nbk#1//% {\expandnexttwo\ettl@ifx{\ettl@car#2\@nil}{\ettl@car#1\@nil}{first}{second}} {\ifcat $\detokenize{#1}$secondoftwo\ettl@csname\fi \ettl@firstspace{#2}{first}{second}}//}% {\ettl@nbk#1//% {\ifcat $\detokenize{#2}$secondoftwo\ettl@csname\fi \ettl@firstspace{#1}{first}{second}} {\ifcat $\detokenize{#1#2}$first\else second\fi}}//% oftwo\endcsname} %% \ifOneToken{ token }{ true }{ false } \newcommand\ifOneToken[1]{\romannumeral\csname rmn@\ettl@firstspace{#1} {\ettl@nbk#1//{second}{\ifcat $\detokenize{#1}$second\else first\fi}//} {\ifcat $\detokenize\expandafter{\ettl@cdr#1\@nil}$% first\else second\fi}oftwo\endcsname} %% \ifsinglechar character{ string }{ true }{ false } \long\def\ifsinglechar#1#2{\romannumeral\csname rmn@\ettl@firstspace{#2} {\ettl@nbk#2//{second}{\ifcat $\detokenize{#1#2}$first\else\ifx#1#2first\else second\fi\fi}//} {\ifcat $\detokenize\expandafter{\ettl@cdr#2\@nil}$% \expandafter\ettl@ifchar \else\expandafter\ettl@carcar \fi{#1}{#2}{first}{second}}% oftwo\endcsname} %% \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}{\ifcat $\detokenize{#1}$second\else first\fi}//} {\ifcat $\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}} {\ifcat $\detokenize{#1}$secondoftwo\ettl@csname\fi \ettl@firstspace{#2}{first}{second}}//}% {\ettl@nbk#1//% {\ifcat $\detokenize{#2}$secondoftwo\ettl@csname\fi \ettl@firstspace{#1}{first}{second}} {\ifcat $\detokenize{#1#2}$first\else second\fi}}//% oftwo\endcsname} %% \ifiscs { string }{ true }{ false } \newcommand\ifiscs[1]{\romannumeral\csname rmn@\ettl@nbk#1//% {\ifcat $\expandafter\ettl@cdr\detokenize{#1}\@nil$secondoftwo\ettl@csname\fi \ifcat $\detokenize\expandafter{\ettl@cdr#1\@nil}$% \expandafter\ettl@firstspace \else secondoftwo\ettl@csname\fi{#1}{second}{first}} {second}//oftwo\endcsname} %% \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^^a7String/} \long\def\ettl@protectspace#1 #2/End^^a7String/{\ifempty{#2}{\z@#1} {\expandafter\@swap\expandafter{\romannumeral\ettl@protectspace#2/End^^a7String/}{\z@#1{ }}}} %% \ifempty{ text }{ true }{ false } \newcommand\ifempty[1]{\romannumeral\csname rmn@\ifcat $\detokenize{#1}$% first\else second\fi oftwo\endcsname} %% \ifnotempty{ text }{ true }{ false } \newcommand\ifnotempty[1]{\romannumeral\csname rmn@\ifcat $\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\ettl@deblank#1/ /} \long\def\ettl@deblank#1 /{\ettl@deblank@i#1/} \long\def\ettl@deblank@i#1/#2{\z@#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^^a7String/}{second}//oftwo\endcsname} \long\def\ettl@numberminus#1-#2/End^^a7String/{\ettl@nbk#2//% {\ettl@nbk#1//{second}{\ettl@numberminus#2/End^^a7String/}//}% {\expandafter\expandafter\expandafter\ettl@numberspace\deblank{#1} /End^^a7String/}//}% \long\def\ettl@numberspace#1 #2/End^^a7String/{\ettl@nbk#2//{second}{\ettl@ifstrnum#1/End^^a7String/}//} \long\def\ettl@ifstrnum#1#2/End^^a7String/{% \ifcsname ettl@number#1\endcsname% #1 detokenized before, ok \ettl@nbk#2//{\ettl@ifstrnum#2/End^^a7String/}{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^^a7String/{##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^^a7String/{#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^^a7String/#2#3[#4]#5{% \expandafter\ettl@Remove@loop #5#1//#2/End^^a7String//End^^a7String/{#3}[{#4-1}]{#5}} \long\def\ettl@Remove@loop#1/#2//#3/End^^a7String/#4[#5]#6{% \ifnum\numexpr#5>0 \ettl@nbk@else#2//% {\ettl@Remove #1#4#2/End^^a7String/{#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^^a7String/{\expandafter\ettl@B@sicFilter #1#3//#2/End^^a7String//End^^a7String/} \long\def\ettl@B@sicFilter#1/#2//#3/End^^a7String/{@\ettl@nbk#3//% {\ifcat $\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 @\ifcat $\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 @\ifcat $\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 @\ifcat $\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 @\ifcat $\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 \@swap{{#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@supergobbleeight{\ettl@supergobble@loop{#1-8}{#2-8}{#3}}% \fi} \long\def\ettl@supergobble@end#1#2#3{\fi\fi\fi#1#2} \long\csdef{ettl@supergobbleeight}#1\fi#2#3#4#5#6#7#8#9{\fi#1} \long\csdef{ettl@supergobble7}#1#2\fi#3#4#5#6#7#8#9{#1} \long\csdef{ettl@supergobble6}#1#2\fi#3#4#5#6#7#8{#1} \long\csdef{ettl@supergobble5}#1#2\fi#3#4#5#6#7{#1} \long\csdef{ettl@supergobble4}#1#2\fi#3#4#5#6{#1} \long\csdef{ettl@supergobble3}#1#2\fi#3#4#5{#1} \long\csdef{ettl@supergobble2}#1#2\fi#3#4{#1} \long\csdef{ettl@supergobble1}#1#2\fi#3{#1} \long\csdef{ettl@supergobble0}#1#2\fi{#1} \long\def\ettl@supergobble@next#1#2#3#4{\fi \ettl@supergobble@loop{#3}0{\ettl@supergobble@end{#4}{#2}}} %% \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@fterGroup\number\numexpr\the\ettl@fter+1}% {\global\csundef{ettl@fterGroup\number\numexpr\the\ettl@fter+1}#1{#2}}% \global\advance\ettl@fter\@ne \expandafter\aftergroup\csname ettl@fterGroup\the\ettl@fter\endcsname} %% \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{\@ifstar\aftergroup@defstar\aftergroup@d@f} \newrobustcmd*\@ftergroup@def[3]{% \aftergroup#2\aftergroup#3\aftergroup#1% \aftergroup\global \aftergroup\undef \aftergroup#1} \newrobustcmd*\aftergroup@defstar[1]{% \global\expandafter\let\csname ettl@ftergroup@def\the\numexpr\ettl@fter+1\endcsname#1% \global\advance\ettl@fter\@ne \expandafter\@ftergroup@def\csname ettl@ftergroup@def\the\ettl@fter\endcsname\let#1} \newrobustcmd*\aftergroup@d@f[1]{% \let\etex@let@primitive\let \def\let{\global\etex@let@primitive}% \expandafter\LetLtxMacro\csname ettl@ftergroup@def\the\numexpr\ettl@fter+1\endcsname#1% \global\advance\ettl@fter\@ne \etex@let@primitive\let=\etex@let@primitive \expandafter\@ftergroup@def\csname ettl@ftergroup@def\the\ettl@fter\endcsname\LetLtxMacro#1}% \let\ettl@aftergroup@def\aftergroup@def %---------------------------------------------------------------------------- %% \@ifchar{ single token }{ true }{ false } \long\def\@ifchar#1#2{\ettl@ifnextchar #1{\@firstoftwo{#2}}} %% \@char@testopt{ code }{ single token }{ default value }{ single token } \newcommand\@char@testopt[4]{\ettl@ifnextchar#2{#1}{#1#2#3#4}} %% \@ifnextchardigit{ true }{ false } \newrobustcmd\@ifnextchardigit[2]{\begingroup \endgroup }% \@ifnextchardigit %% \ettl@ifnextchar{ character token }{ true }{ false } \newrobustcmd\ettl@ifnextchar[3]{\begingroup \long\edef\1##1/##2/##3{##1\endgroup\unexpanded{#2}##3}% \long\edef\2##1/##2/##3{##1\endgroup\unexpanded{#3}##3}% \ifOneToken{#1} {\csname ettl@\ifcat $\expandafter\ettl@cdr\detokenize{#1}\@nil$% OneChar xifnch\else xifntk\fi\endcsname{#1}} {\2//{}}} \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@\ifcat $\detokenize{#3}$1\else2\fi of2\endcsname {\let \ettl@x \@empty \letcs \ettl@futur@def@collect{\@gobblescape#1@collectall}}% {\def \ettl@x {#3}\edef \ettl@y {#2{#3}}% \ifx\ettl@x\ettl@y \let\ettl@y\@gobble \else \ifx#2\unexpanded \let\ettl@y\@gobble \else \def\ettl@y{\edef\ettl@x}% \fi\fi\ettl@y{\detokenizeChars{#3}}% \letcs\ettl@futur@def@collect{\@gobblescape#1@collect}}% \expandafter#1\expandafter#2\expandafter{\ettl@x}} \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^^a4t/{#2}{##1}}% \long \def \ettl@futuredef@end##1##2/Ne^^a4t/##3##4{##2\endgroup\def#3{##4}#4##1}% \futurelet \ettl@x \ettl@futuredef@loop} \long\def\ettl@futuredef@collect#1#2/Ne^^a4t/#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^^a4t/{}{#4}}/Ne^^a4t/} \long\def\ettl@futuredef@space#1#2/Ne^^a4t/#3#4 {% \ettl@futur@def@collect#1#2/Ne^^a4t/{#3}{#4}{ }} \long\def\ettl@futuredef@collectall#1#2/Ne^^a4t/#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^^a4t/{##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^^a4t/{##1}{#2}{}}% \long \def \ettl@futured@f@end##1/Ne^^a4t/##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^^a4t/#3#4#5 {% \ettl@futur@def@collect#1#2/Ne^^a4t/{#3}{#4}{#5}{ }} \long\def\ettl@futured@f@collect#1#2/Ne^^a4t/#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^^a4t/{#3}{}{#6}}% {\ettl@futured@f@try@expand{#3}\ettl@futured@f@end{#6}}/Ne^^a4t/} \long\def\ettl@futured@f@collectall#1#2/Ne^^a4t/#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^^a4t/#3#4#5 {% \ettl@futur@def@collect#1#2/Ne^^a4t/{#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^^a4t/{#1}{}{#3}} \long\def\ettl@futured@f@expand/Ne^^a4t/#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^^a4t/#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^^a7List/} \long\def\ettl@dosinglelist@loop#1#2#3#4/#5#6#7/End^^a7List/{% #1{#2}#6{#3}#4//{#6}{#7}/End^^a7List/} %% \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^^a7List/} \long\def\ettl@singlelist@loop#1#2#3#4#5/#6#7#8/End^^a7List/{% #7{#4} {{#1+1}{#2+1+0*(0}{#4}} {{#1+1}{#2+1}{#3}}#5//{#7}{#8}/End^^a7List/} % \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^^a7List/} \def\ettl@singlelist@result#1#2#3#4/End^^a7List/{\ExpandNextTwo\@swaptwo% {\number\numexpr\ifempty{#3}{-1}{#2)}}{\number\numexpr#1}{#3}} \def\ettl@setresult#1of#2>#3<{\ettl@nbk #3//% {\ettl@set@result#1of#2>#3<} {\csname ettl@#1of#2\endcsname}//} \def\ettl@set@result#1of#2>#3<#4{\ifdefcount{#3} {#3=\csname ettl@#1of#2\endcsname#4} {\expandafter\edef\noexpand#3{\csname ettl@#1of#2\endcsname{#4}}}% } %% \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{\ifx##10\expandafter\relax\fi}}% }{\ettl@breakloop{}}///End^^a7List/}}% #1\long\def#5##1##2#3##3##4/##5##6##7/End^^a7List/{% \ifcat $\detokenize{##2}$\expandafter\@gobbletwo\fi\@firstofone{##1{##2}}% ##6{##1}##3##4//{##6}{##7}/End^^a7List/} #1\long\def#6##1##2##3#3##4##5/##6##7##8/End^^a7List/{% \ifcat $\detokenize{##3}$\expandafter\@gobbletwo\fi\@firstofone{##2[##1]{##3}}% \expandafter##7\expandafter{\number\numexpr##1+1}{##2}##4##5//{##7}{##8}/End^^a7List/} #1\protected\def#7{\@ifchar*% {\@ifchar+{\ettl@forloop{\expandafter#2\expandafter*\expandafter+}{[####1]####2}} {\ettl@forloop{\expandafter#2\expandafter*}{####1}}} {\@ifchar+{\@ifchar*% {\ettl@forloop{\expandafter#2\expandafter*\expandafter+}{[####1]####2}} {\ettl@forloop{\expandafter#2\expandafter+}{[####1]####2}}} {\ettl@forloop{\expandafter#2}{####1}}}} #1\def#2{\ettl@lst@modif#423\ifiscs}} \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^^a7List/{#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% }% \ettl@for@nested %% \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^^a7List/{##6[##1+1]##2#5##3##4//##6##7/End^^a7List/}% \ifnotempty{#5}%% special case if no separator {\long\def#4[##1]#5##2#5#5##3//##4/End^^a7List/{\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^^a7List/{\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^^a7List/}% \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 } \edef\ettl@restore@catcode{\catcode124 \the\catcode124}% |=124 \catcode`\|=3 \newrobustcmd\listdel[1][]{\ettl@RemoveInList{}\listdel|{#1}} \newrobustcmd\listgdel[1][]{\ettl@RemoveInList\global\listdel|{#1}} \newrobustcmd\listedel[1][]{\ettl@listedel{}\listdel|{#1}} \newrobustcmd\listxdel[1][]{\ettl@listedel\global\listdel|{#1}} \ettl@restore@catcode\undef\ettl@restore@catcode \newrobustcmd\ettl@listedel[6]{\begingroup\protected@edef#5{#6}\expandafter\endgroup \expandafter\@swaparg\expandafter{#5}{\ettl@RemoveInList#1#2{#3}{#4}#5}} %% \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\long\def\ettl@getlistindex##1#4#6#4##2/End^^a7List/{\endgroup \ExpandAftercmds{\ettl@setresult 1of1>#1<}{\ettl@nbk##2//{#3*!{##1}}{-1}//}% }#2\ettl@getlistindex#5#4#6#4/End^^a7List/} \newrobustcmd\getlistindex{\@ifstar {\@testopt{\ettl@get@listindex\relax}{}} {\@testopt{\ettl@get@listindex\expandafter}{}}} \begingroup\catcode`\|=3% etb catcode \protected\long\gdef\ettl@get@listindex#1[#2]#3#4{% \ifx#1\relax \ettl@getlistindex{#2}{}\listloop|{#4}{#3}% \else \ifiscs{#4} {\ettl@getlistindex{#2}#1\listloop|{#4}{#3}} {\ettl@getlistindex{#2}\listloop|{#4}{#3}}% \fi} \endgroup%\catcode group %\getcsvlistindex [\result]{ item }{ csvlistmacro } %\getcsvlistindex*[\result]{ item }{ item,item,item } \newrobustcmd\getcsvlistindex{\@ifstar {\@testopt{\ettl@get@csvlistindex\relax}{}} {\@testopt{\ettl@get@csvlistindex\expandafter}{}}} \protected\long\gdef\ettl@get@csvlistindex#1[#2]#3#4{% \ifx#1\relax \ettl@getlistindex{#2}{}\csvloop,{#4}{#3}% \else \ifiscs{#4} {\ettl@getlistindex{#2}#1\csvloop,{#4}{#3}} {\ettl@getlistindex{#2}\csvloop,{#4}{#3}}% \fi} \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^^a7List/{\endgroup\ifnotblank{##2}% }#2\ettl@tempa#2#1#3#1#4#1/End^^a7List/} \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 - not to be used - experimental \ProcessOptions*\relax \endinput %% %% End of file `etextools.sty'.