From e5bc967eb0517b8377d70914cc45484e5f4f2c7c Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Fri, 14 Aug 2009 23:52:07 +0000 Subject: etextools (11aug09) git-svn-id: svn://tug.org/texlive/trunk@14676 c570f23f-e606-0410-a88d-b1316a301751 --- .../source/latex/etextools/etextools.dtx | 1097 +++++++++++++------- .../source/latex/etextools/etextools.ins | 2 +- 2 files changed, 699 insertions(+), 400 deletions(-) (limited to 'Master/texmf-dist/source/latex/etextools') diff --git a/Master/texmf-dist/source/latex/etextools/etextools.dtx b/Master/texmf-dist/source/latex/etextools/etextools.dtx index 5a8c2dcef83..3c335b7296d 100644 --- a/Master/texmf-dist/source/latex/etextools/etextools.dtx +++ b/Master/texmf-dist/source/latex/etextools/etextools.dtx @@ -1,6 +1,5 @@ % \iffalse meta-comment %%% etextools : more e-TeX useful tools for LaTeX package writers -%%% Florent CHERVET % % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either @@ -97,18 +96,20 @@ and etextools-examples.tex \documentclass[a4paper,oneside]{ltxdockit} \usepackage[latin9]{inputenc} \usepackage[american]{babel} -\usepackage{doc,stmaryrd,amsmath,graphics,geometry,fancyhdr,framed,bbding,trace,embedfile}\CodelineNumbered +\usepackage{doc,tocloft,stmaryrd,amsmath,graphics,geometry,fancyhdr,framed,bbding,trace,embedfile,etoolbox,marvosym} +\CodelineNumbered\CodelineIndex \embedfile{\thisfile.dtx} -\geometry{totalheight=26cm,marginparwidth=14pt} +\geometry{left=4.5cm,marginparwidth=14pt,right=2cm,totalheight=26cm} \titlepage{% title={The \sty{etextools} package}, subtitle={An \etex package providing useful tools for LaTeX Users \\ and package Writers}, url={http://www.ctan.org/tex-archive/macros/latex/contrib/etextools/}, author={Florent CHERVET}, email={florent.chervet@free.fr}, - revision={2\:$\boldsymbol{\varepsilon}$}, - date={14 July 2009}} + revision={2\:$\boldsymbol{\zeta}$}, + date={12 août 2009}} \hypersetup{% + hyperindex=true, pdftitle={The etextools package}, pdfsubject={An e-TeX package for more useful tools for LaTeX package writers}, pdfauthor={Florent CHERVET}, @@ -121,13 +122,65 @@ and etextools-examples.tex % % \fi % +% \CheckSum{887} +% +% \CharacterTable +% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z +% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z +% Digits \0\1\2\3\4\5\6\7\8\9 +% Exclamation \! Double quote \" Hash (number) \# +% Dollar \$ Percent \% Ampersand \& +% Acute accent \' Left paren \( Right paren \) +% Asterisk \* Plus \+ Comma \, +% Minus \- Point \. Solidus \/ +% Colon \: Semicolon \; Less than \< +% Equals \= Greater than \> Question mark \? +% Commercial at \@ Left bracket \[ Backslash \\ +% Right bracket \] Circumflex \^ Underscore \_ +% Grave accent \` Left brace \{ Vertical bar \| +% Right brace \} Tilde \~} +% +% \DoNotIndex{\begin,\CodelineIndex,\CodelineNumbered,\def,\DisableCrossrefs,\if} +% \DoNotIndex{\DocInput,\documentclass,\EnableCrossrefs,\end,\GetFileInfo} +% \DoNotIndex{\NeedsTeXFormat,\OnlyDescription,\RecordChanges,\usepackage} +% \DoNotIndex{\ProvidesClass,\ProvidesPackage,\ProvidesFile,\RequirePackage} +% \DoNotIndex{\filename,\fileversion,\filedate,\let} +% \DoNotIndex{\@listctr,\@nameuse,\csname,\else,\endcsname,\expandafter} +% \DoNotIndex{\gdef,\global,\if,\item,\newcommand,\nobibliography} +% \DoNotIndex{\par,\providecommand,\relax,\renewcommand,\renewenvironment} +% \DoNotIndex{\stepcounter,\usecounter,\nocite,\fi} +% \DoNotIndex{\@fileswfalse,\@gobble,\@ifstar,\@unexpandable@protect} +% \DoNotIndex{\AtBeginDocument,\AtEndDocument,\begingroup,\endgroup} +% \DoNotIndex{\frenchspacing,\MessageBreak,\newif,\PackageWarningNoLine} +% \DoNotIndex{\protect,\string,\xdef,\ifx,\texttt,\@biblabel,\bibitem} +% \DoNotIndex{\z@,\wd,\wheremsg,\vrule,\voidb@x,\verb,\bibitem} +% \DoNotIndex{\FrameCommand,\MakeFramed,\FrameRestore,\hskip,\hfil,\hfill,\hsize,\hspace,\hss,\hbox,\hb@xt@,\endMakeFramed,\escapechar} +% \DoNotIndex{\do,\date,\if@tempswa,\@tempdima,\@tempboxa,\@tempswatrue,\@tempswafalse,\ifdefined,\ifhmode,\ifmmode,\cr} +% \DoNotIndex{\box,\author,\advance,\multiply,\Command,\outer,\next,\leavevmode,\kern,\title,\toks@,\trcg@where,\tt} +% \DoNotIndex{\the,\width,\star,\space,\section,\subsection,\textasteriskcentered,\textwidth} +% \DoNotIndex{\",\:,\@empty,\@for,\@gtempa,\@latex@error,\@namedef,\@nameuse,\@tempa,\@testopt,\@width,\\,\m@ne,\makeatletter,\makeatother} +% \DoNotIndex{\maketitle,\parindent,\setbox,\x,\kernel@ifnextchar} +% \DoNotIndex{\un,\deux,\xx,\tt,\title,\times,\texttt,\tableofcontents,\&,\@preline,\@redef,\\,\`,\|,\ ,\author} +% \DoNotIndex{\bfseries,\clearpage,\cmd,\csvloopTest,\defineparser,\endinput,\expandnextTest} +% \DoNotIndex{\fancyhf,\fancyhead,\FE@testoptTest,\FE@ifstarTest,\get@params,\goodbreak,\hypersetup,\iffirstcharTest,\ifsinglecharTest} +% \DoNotIndex{\llap,\rlap,\longrightarrow,\make@macro,\makequotes,\MakeShortVerb,\mdseries,\multicolumn,\mylist} +% \DoNotIndex{\nobreak,\noindent,\null,\OPTmacro,\notstarred,\pagestyle,\preline,\quad,\result,\smex,\starmacro,\starred,\strip@macro} +% \DoNotIndex{\strip@macroprefix,\strip@meaning,\strip@prefix,\sty,\subsubsection,\subtitle,\test} +% \DoNotIndex{\testcsvloop,\testexpandnext,\testFE@testopt,\testFE@ifstar,\testgetlistitem,\testiffirstchar,\testifsinglechar,\getlistitemTest} +% \DoNotIndex{\textbf,\textcolor,\vskip,\long,\hrulefill,\&,\@get@params,\geometry,\edef,\BySeven,\optmacro,\@xifblank,\ettl@onlyonce,\ettl@undefined,\usercmd,\noexpand} +% \DoNotIndex{\@listedel,\@listgdel,\@listxdel} +% % \makeatletter % \def\thispackage{\sty{\thisfile}} % \font\ding=dingbat scaled 800 +% \hypersetup{hyperindex=true} % \fancyhf{}\fancyhead[L]{The \sty{etextools} package -- an \eTeX\, package for \LaTeX} % \fancyfoot[L]{\color[gray]{.35}\scriptsize\thispackage\quad\copyright\,\lower.3ex\hbox{\NibRight}\,Florent Chervet} % \fancyfoot[R]{\oldstylenums{\thepage} / \oldstylenums{\pageref{LastPage}}} % \pagestyle{fancy} +% \fancypagestyle{plain}{% +% \fancyhf{}\let\headrulewidth\z@ +% \fancyfoot[R]{\oldstylenums{\thepage} / \oldstylenums{\pageref{LastPage}}}} % \def\CTAN#1{\href{http://www.ctan.org/tex-archive/#1}{\nolinkurl{CTAN:#1}}} % \definecolor{spot}{rgb}{.7,0.1,0.2} % \newcommand\fecccolor{\color{fecc}}\definecolor{fecc}{rgb}{.2,.6,.2} @@ -145,22 +198,34 @@ and etextools-examples.tex % \catcode`\§\active\def§{\par\nobreak\vskip-\parskip} % \renewcommand\partformat{}\let\thepart\partformat\renewcommand\raggedpart{\centering} % \newcommand\cmdref[1]{\hyperref[#1]{\underline{\sty{\reflinkcolor\textbackslash #1}}}} -% \newcommand\cmdlabel[1]{\label{#1}} -% \def\FE{\setbox8\hbox{$\m@th\bindnasrepma$}% -% \marginpar{\fecccolor\scalebox{2}{$\copy8\mkern-13.5mu\copy8\mkern-13.5mu\copy8$}}\space} +% \newcommand\cmdlabel[1]{\label{#1}\hyperdef{cmdlabel}{#1}{}} +% \newcommand\seeimpl[1]{% +% \ifblank{#1}{\colorbox{yellow}{\textcolor{red}{\LARGE\Laserbeam}}} +% {\hfill \hyperref{}{cmdlabel}{impl:#1}{\colorbox{yellow}{\textcolor{red}{\LARGE\Laserbeam}}}}} +% \newsavebox\seedescbox +% \setbox\seedescbox\hbox{\rlap{\kern.4em\colorbox{green}{\textcolor{red}{\SunshineOpenCircled}}}} +% \newcommand\seedesc[1]{% +% \ifblank{#1}{\copy\seedescbox} +% {\vadjust{\vskip-1.5\ht\seedescbox\hfill +% \hbox{\rlap{\kern.4em\hyperref{}{cmdlabel}{#1}{\colorbox{green}{\textcolor{red}{\SunshineOpenCircled}}}}}}}} +% \def\FE{\setbox8\hbox{$\m@th\bindnasrepma$}% +% \marginpar{\raisebox{-2pt}{{\fecccolor\scalebox{2}{$\copy8\mkern-13.5mu\copy8\mkern-13.5mu\copy8$}}}}\space} % \def\smex{\leavevmode\hb@xt@2em{\hfil\spotcolor$\longrightarrow$\hfil}} % \font\manual=manfnt\def\dbend{\marginpar{\manual\char127}\space} % \parindent\z@\topsep\z@\partopsep\z@\parskip.3\baselineskip +% \cftbeforesecskip=4pt +% \cftbeforepartskip=11pt +% \let\footnoterule\relax % \lastlinefit999 % \makeatother % -% \thispagestyle{plain}\printtitlepage +% \thispagestyle{plain}\printtitlepage\medskip % \fontfamily{ua1}\selectfont -% \tableofcontents\vfil +% \tableofcontents\medskip\enlargethispage{\baselineskip}\thispagestyle{plain} % % \begin{shaded}\parindent0pt\noindent\large % -% {\bfseries\catcode`\ \active\let =\,\hfil \* A b s t r a c t \*\hfil}\par +% {\bfseries\catcode`\ \active\let =\,\hfil\NibSolidRight A b s t r a c t \NibSolidLeft\hfil}\par % % The \sty{etextools} package is based on the \sty{etex} and \sty{etoolbox} % packages and defines more tools for \LaTeX\ Users or package Writers. @@ -173,15 +238,15 @@ and etextools-examples.tex % % The main contributions of this package are : % \begin{itemize} -% \item the \cmdref{expandnext} macro; +% \item the \cmdref{expandnext} macro and the \cmdref{ifempty} macro % \item the ability to define fully expandable macros with parameter and/or star version (with a small restriction) -% -- see \cmdref{FE@testopt}, \cmdref{FE@ifstar}; +% -- see \cmdref{FE@testopt}, \cmdref{FE@ifstar} % \item a Command-List Parser constructor that fully uses this new feature : command-list parser are fully expandable -% -- see \cmdref{csvloop} and \cmdref{listloop}; +% -- see \cmdref{csvloop} and \cmdref{listloop} % \item three macros that are lacking from the \sty{etoolbox} package for removing elements from lists : -% \cmdref{listdel} and \cmdref{listgdel}, \cmdref{listxdel}; +% \cmdref{listdel} and \cmdref{listgdel}, \cmdref{listedel}, \cmdref{listxdel} % \item macros that return the index of an item in a list: \cmdref{getlistindex} and \cmdref{xgetlistindex} and conversely -% the item at a given position in a list: \cmdref{getlistitem}; +% the item at a given position in a list: \cmdref{getlistitem} % % \end{itemize} % @@ -198,7 +263,358 @@ and etextools-examples.tex % % \section{Introduction} % -% \subsection{Identification} +% \subsection{Motivation} +% +% The first motivation for this package was to define a list-parser macro: +% \begin{itemize} +% \item just like the \cs{docsvlist} and \cs{dolistloop} macros from \sty{etoolbox} +% \item fully expandable (\ie in an |\edef|) +% \item that take the auxiliary command(s) (\cs{do} in \sty{etextools}) as an optional argument. +% \end{itemize} +% +% As a result, a method for defining fully expandable macros with optional parameter is built here. +% +% \subsection{Purely Expandable macros} +% +% The \FE fully expandable (or purely expandable) commands defined in this package +% can be easily spotted with the special marker displayed here in the margin for information. +% \medskip +% +% Go directly to the implementation of a\marginpar{\llap{\seeimpl{}\hskip-1.5em}} command by clicking +% on the symbol displayed here in the margin for information. +% \medskip +% +% Now from the implementation, \marginpar{\llap{\seedesc{}\kern4pt}} you can return to the description +% section just by clicking on the symbol displayed here in the margin for information. +% +% \subsection{The example file} +% +% The example file provided with \thispackage\ illustrates the macros defined here. +% +% \subsection{Requirements} +% +% This package requires the packages \sty{etex} package by David Carlisle and +% \sty{etoolbox} by Philipp Lehman. +% +% \subsection{Acknowledgements -- Thank You !} +% +% Thanks to Philipp Lehman for the \sty{etoolbox} package (and also for this nice class of documentation). +% Much of my work on lists are based on his work and package. +% +% \clearpage +% \part*{All User Commands} +% \addtocontents{toc}{\protect\contentsline{part}{All User Commands}{}{}} +% +% \section{Expansion control} +% +% \begin{ltxsyntax} +% +% \cmditem{expandnext}{cstoken}{first parameter of cstoken} \cmdlabel{expandnext} \seeimpl{expandnext} +% +% We\FE often want a control sequence to be expanded after its first argument. For example, if you +% want to test if a command |\foo| has a blank replacement text you will say: +% +% \qquad |\expandafter\ifblank\expandafter{\foo}{|\prm{true part}|}{|\prm{false part}|}| +% +% With |\expandnext| you'll just have to say: +% +% \qquad |\expandnext\ifblank{\foo}{|\prm{true part}|}{|\prm{false part}|}| +% +% Now observe the following game : +% \begin{tabbing} +% \qquad\= |\def\foo{foo}| \qquad \= \smex \qquad \= |\def\Foo{\foo}| \quad \= \eol \\ +% \> |\def\\FOo{\Foo}| \> \smex \> |\def\FOO{\FOo}| \> \eol \\ +% \> |\def\fool{\FOO}| +% \end{tabbing} +% Guess how many \cmd{expandafter} are needed to test ``|\ifblank{foo}|'' directly from |\fool| ??? +% +% |\expandnext| solves this problem : |\fool| has 5 degrees of expansion until it expands to ``foo'', therefore exactly 5 +% |\expandnext| are required. The solution is: +% +% \qquad |\expandnext\expandnext\expandnext\expandnext\expandnext\ifblank{\fool}| +% +% Other example: suppose you want to define a macro |\detokenizecs{|\prm{csname}|}| that expands to the detokenized content +% of |\csname |\prm{csname}|\endcsname|. Without |\expandnext| you will have to say: +% \begin{tabbing} +% \qquad\= |\expandafter\expandafter\expandafter\detokenize| \\ +% \> |\expandafter\expandafter\expandafter{\csname |\prm{csname}|\endcsname}| +% \end{tabbing} +% \textbf{six} \cmd{expandafter}(s). With |\expandnext| you just have to say:§ +% \qquad|\expandnext\expandnext\detokenize{\csname #1\endcsname}| +% +% \cmditem{noexpandcs}{csname} \cmdlabel{noexpandcs}\seeimpl{noexpandcs} +% +% In an \FE expansion context (|\edef|) we often want a control sequence whose name results +% from the expansion of some macros and/or other tokens to be created, but not expanded at that point. +% Roughly:§ +% \qquad |\edef{\noexpandcs{}}|§ +% will expand to: |\"cs-name"| but this (new) control sequence itself will not be expanded. +% A typical use is shown in the following code:§ +% \smex |\edef\abc{\noexpandcs{abc@\@gobblescape\controlword}}|§ +% \smex if equivalent to:\quad|\def\abc{\abc@controlword}|. +% +% {\rmk|\noexpandcs| may be abbreviated f.ex. in |\`#1`| in |\edef| that take place in a group. } +% +% \cmditem{noexpandafter}\cmdlabel{noexpandafter}\seeimpl{noexpandafter} +% +% |\noexpandafter|\FE only means |\noexpand\expandafter| and is shorter to type. +% +% {\rmk This command is used in the definition of \cmdref{DeclareCmdListParser}.} +% +% \end{ltxsyntax} +% +% \clearpage +% \section{Characters and Strings} +% +% \begin{ltxsyntax} +% +% \cmditem{ifempty}{string}{true}{false} \cmdlabel{ifempty} \seeimpl{ifempty} +% +% |\ifempty|\FE is similar to |\ifblank| but it test if a string is really empty +% (it shall not contain any character nor spaces). To test if the replacement +% text of a macro is empty, one may use |\ifempty| in conjunction with |\expandnext|: +% \begin{tabbing} +% \quad\=|\expandnext\ifempty{\macro}| \prm{true}\prm{false} +% \end{tabbing} +% +% +% \cmditem{deblank}{string} \cmdlabel{deblank} \seeimpl{deblank} +% +% |\deblank|\FE removes all leading and trailing blank spaces from its argument.\medbreak +% +% \cmditem{xifblank}{string}{true}{false} \seeimpl{xifblank} +% +% |\xifblank| is similar to |\ifblank| except that the \prm{string} is first expanded +% with |\protected@edef|.\medbreak +% +% \cmditem{xifstrequal}{string1}{string2}{true}{false}\cmdlabel{xifstrequal}\seeimpl{xifstrequal} +% +% |\xifstrequal| is similar to |\ifstrequal| but each \prm{string} argument +% is expanded with |\protected@edef| before comparison.\medbreak +% +% \cmditem{iffirstchar}{string1}{string2}{true}{false} \cmdlabel{iffirstchar}\seeimpl{iffirstchar} +% \cmditem*{iffirstchar}{}{string}{true}{false} +% +% |\iffirstchar| \FE compares the character codes of the \textbf{first} characters of each \prm{string}. The +% comparison is \emph{catcode agnostic} and the macro is fully expandable. Neither \prm{string1} nor \prm{string2} +% is expanded before comparison. Example:§ +% \qquad|\iffirstchar *{*hello*}{begins with a star}{begins with something else}| +% +% There is a ``special'' use of this command when one want to test if a \prm{string} begins +% with an \emph{escape} character (\,\textbackslash\,) one may say: +% \begin{tabbing} +%\qquad\= |\iffirstchar \@backslashchar{|\prm{string}|}|\qquad\= or even easier:\\ +% \>|\iffirstchar {}{|\prm{string}|}| +% \end{tabbing} +% +% Please note that the tests: +% \begin{tabbing} +% \qquad\qquad\=|\iffirstchar |\=|{|\prm{whatever string1 is}|}{}|\\ +% and:\>|\iffirstchar |\>|{}{}| +% \end{tabbing} +% are \textbf{always expanded into \underline{\prm{false}}} +% (for consistency with the shortcut-test for |\@backslashchar|).\medbreak +% +% \cmditem{ifsinglechar}{string1}{string2}{true}{false} \cmdlabel{ifsinglechar}\seeimpl{ifsinglechar} +% +% |\ifsinglechar|\FE performs the test |\iffirstchar| but only if \prm{string2} has one single character. +% +% Now with the macro |\ifsinglechar| it becomes possible to write fully expandable macros with an option, \textbf{provided +% that this macro has at least one non-optional argument}, as far as we don't use |\futurelet| nor any assignation. +% The ``trick'' is the following: +% \begin{tabbing} +% \qquad\= |\def\MacroWithOption#1{\ifsing|\=|lechar|\=|[{#1}| \\ +% \>\>|{\MacroHasOption[}| \\ +% \>\>|{\MacroNoOption{#1}}}}|\\ +% \> |\def\MacroHasOption[#1]#2|... \>\textit{definition} \\ +% \> |\def\MacroNoOption#1|...\>\textit{definition} +% \end{tabbing} +% +% \clearpage +% Moreover (in the style of |\@testopt|): +% \begin{tabbing} +% \qquad\= |\def\MacroWithOption#1{\ifsing|\=|lechar|\=|[{#1}|\\ +% \>\>|{\MacroHasOption#1}|\\ +% \>\>|{\MacroHasOption[default]{#1}}}| +% \end{tabbing} +% +% \end{ltxsyntax} +% +% \section{Fully expandable macros with options} +% +% \begin{ltxsyntax} +% +% \cmditem{FE@testopt}{argument to be tested}{commands}{default option} \cmdlabel{FE@testopt}\seeimpl{FE@testopt} +% +% |\FE@testopt|\FE mimics the behaviour of |\@testopt| but is Fully Expandable (\sty{FE}) and can be used as follow:§ +% \qquad |\def\MacroWithOption#1{\FE@testopt{#1}\MacroHasOption{default}}|\par +% +% Note that |\MacroWithOption| \textbf{must have at least one mandatory argument.}\medbreak +% +% {\rmk |\FE@testopt| is used in the definition of \cmdref{DeclareCmdListParser}.} +% +% \cmditem{FE@ifstar}{argument to be tested}{star-commands}{non-star commands} \cmdlabel{FE@ifstar}\seeimpl{FE@ifstar} +% +% Similarly,\FE it becomes possible to mimic the behaviour of |\@ifstar| but in a fully expandable(\sty{FE}) way. +% |\FE@ifstar| can be used as follow :§ +% \begin{tabbing} +% \qquad\= |\def\StarOrNotCommand#1{\FE@|\=|ifstar|\=|{#1}|\\ +% \>\>|{\StarredCommand}|\\ +% \>\>|{\NotStarredCommand}}| +% \end{tabbing} +% +% Remember that |\StarredCommand| and |\NotStarredCommand| \textbf{must have at least one mandatory argument.} +% +% % {\rmk |\FE@ifstar| is used in the definitions of \cmdref{DeclareCmdListParser}, \cmdref{csvloop}, \cmdref{listloop} +% and \cmdref{csvtolist}.} +% +% \end{ltxsyntax} +% +% \section{Lists management} +% +% \subsection{The Command-List Parser} +% +% The \sty{etoolbox} package provides a way to define list parsers a fully expandable macros: +% the list parser is able to expand the auxiliary command |\do| on each item of a list. +% \iffalse +% Declaration of a list parser is done via the |\DeclareListParser| macro\footnotemark. +% \footnotetext{besides, \sty{etoolbox} defines the \sty{\textbackslash docsvlist} and the +% \sty{\textbackslash dolistloop} macros: the choice of this name is not very friendly +% and we expected to have a \sty{\textbackslash docsvloop} macro instead...}. +% \fi +% +% Here we provide a |\DeclareCmdListParser| macro that is compatible and slightly different, because the auxiliary +% command is not necessarily |\do|. Such a command-list-parser is fully expandable. +% +% The idea is that if |\csvloop| has been defined as a command-parser then, thank to the fully expandable macro |\FE@testopt| +% we can call for expansion: +% \begin{tabbing} +% \qquad\= |\csvloop*{item,item,...}|\,\= as a shortcut for\,\= |\csvloop*[\do]{item,...}|\\ +% or:\> |\csvloop*[\listadd\mylist]{item,item,...}|\quad +% \end{tabbing} +% for example to convert the csv-list into internal \sty{etoolbox} list. +% +% {\rmk The star-form of \cmdref{csvloop} will be explained below.} +% +% \begin{ltxsyntax} +% +% \cmditem{DeclareCmdListParser}{command}{separator}\cmdlabel{DeclareCmdListParser}\seeimpl{DeclareCmdListParser} +% +% |\DeclareCmdListParser| acts in the same way as \sty{etoolbox}-|\DeclareListParser| and the command-list-parser +% are sensitive to the category code of the \prm{separator} +% {\catcode`\ =13\let =-\it(which is not necessarily a single character and shall not be a {\tt\string&} with a catcode of 3)}. +% +% A Command-List-Parser is then defined as a purely expandable macro. It has a \textit{star form} for the case +% of the list given is already expanded, and a \textit{normal form} if the list is given as a macro name. +% +% You may then use the following syntaxes: +% \begin{tabbing} +% \qquad\=|\CmdListParser\mylist| \\ +% \>|\CmdListParser*{item|\prm{sep}|item|\prm{sep}|item}| \\ +% \>|\CmdListParser[\Commands]\mylist| \\ +% or:\>|\CmdListParser*[\Commands]{item|\prm{sep}|item|\prm{sep}|item}| +% \end{tabbing} +% +% \subsection{Loops into lists} +% +% Now we have to declare two command-list-parsers : |\listloop| for \sty{etoolbox} lists +% and |\csvloop| for comma-separated lists. +% +% \cmditem{csvloop}[auxiliary commands]{csvlistmacro} \cmdlabel{csvloop}\seeimpl{csvloop} +% \cmditem*{csvloop*}[auxiliary commands]{item,item,item,...} +% \cmditem*{listloop}[auxiliary commands]{listmacro} \cmdlabel{listloop} +% \cmditem*{listloop*}[auxiliary commands]{expanded list} +% +% |\listloop|\FE acts exactly as \sty{etoolbox}-|\dolistloop| with an optional argument to change +% the default auxiliary command |\do| to apply to each item of the list : +% \begin{tabbing} +% \qquad\=|\listloop\mylist|\;\=\textit{is}\;\= |\listloop[\do]\mylist|\;\=\textit{and is also}\;\= |\dolistloop\mylist|\\ +% \> |\csvloop\csvlist|\> \textit{is}\> |\csvloop[\do]\csvlist|\> \textit{and is also}: \eol \\ +% \>\>\> |\expandafter\docsvlist\expandafter{\csvlist}| +% \end{tabbing} +% +% +% \subsection{Converting csv lists to \sty{etoolbox}-lists} +% +% \cmditem{csvtolist}{listmacro}{csvlistmacro} \cmdlabel{csvtolist}\seeimpl{csvtolist} +% \cmditem*{csvtolist*}{listmacro}{item,item,item...} +% +% |\csvtolist| converts a comma separated list into an internal \sty{etoolbox} list. It is useful to insert more than one item +% at a time in a list. Those macros are not fully expandable because of the redefinition of \prm{listmacro} done by |\listadd|... +% +% It's also the first application of the \cmdref{csvloop} macro just defined. +% +% +% \cmditem{csvtolistadd}{listmacro}{csvlistmacro} \cmdlabel{csvtolistadd}\seeimpl{csvtolistadd} +% \cmditem*{csvtolistadd*}{listmacro}{item,item,item...} +% +% |\csvtolistadd| acts similarly but does not reset the \prm{listmacro} to |\@empty|: +% +% +% \subsection{Removing elements from \sty{etoolbox}-lists} +% +% The \sty{etoolbox} package provides |\listadd|, |\listgadd| and |\listxadd| commands +% to add items to a list. However, no command is designed to remove an element from a +% list. +% +% +% \cmditem{listdel}{listmacro}{item} \cmdlabel{listdel}\seeimpl{listdel} +% \cmditem*{listgdel}{listmacro}{item} \cmdlabel{listgdel} +% \cmditem*{listedel}{listmacro}{item} \cmdlabel{listedel} +% \cmditem*{listxdel}{listmacro}{item} \cmdlabel{listxdel} +% +% The |\listdel| command removes the element \prm{item} from the list \prm{listmacro}. Note that the +% \prm{listmacro} is redefined after deletion: +% +% Commands |\listgdel| and |\listxdel| are similar, except that the assignment (\ie the redefinition +% of the list) is global; for the latter, the \prm{item} is first expanded using |\protected@edef|: +% +% +% \subsection{Index of an element in a list} +% +% +% \cmditem{getlistindex}{item}{listmacro} \cmdlabel{getlistindex}\seeimpl{getlistindex} +% \cmditem*{xgetlistindex}{item}{listmacro} \cmdlabel{xgetlistindex} +% \cmditem*{getlistindex*}{item}{list} +% \cmditem*{xgetlistindex*}{item}{list} +% +% Sometimes it is interesting to know at which offset in a list lies a given item. |\getlistindex| answers to this question. +% |\xgetlistindex| does the same thing but expand the \prm{item} (using |\protected@edef|) prior looking for it in the list. +% The result (\ie the position of \prm{item} in \prm{list}) is stored in |\indexinlist|. +% \begin{itemize} +% \item \ If \prm{item} is not found in the \prm{list} then |\indexinlist| is 0 +% \item \ If \prm{item} is found in first position then |\indexinlit| is 1 and so on. +% \end{itemize} +% +% As for the command-list-parser, the star versions are designed in case the list (in the second argument) is already expanded. +% +% +% \subsection{Extract by index from a list} +% +% \begin{ltxsyntax} +% +% \cmditem{getlistitem}{listmacro}{index [numexpr expression]} \cmdlabel{getlistitem}\seeimpl{getlistitem} +% \cmditem*{getlistitem*}{list}{index [numexpr expression]} +% +% Now\FE the reverse operation of ``getting the index'' is ``getting the element'' whose index is known. Note that this macro +% is fully expandable for we don't have to compare the items (just count the loop using |\numexpr| -- no counter). Therefore we use the +% fully expandable version of |\ifstar| : \cmdref{FE@ifstar} to keep the ``fully-expand-ability'' of the star-form as well: +% \begin{itemize} +% \item \ If the \prm{index} is in the range $[1\dots n]$ then the macro expands to \prm{item}$_n$ +% \item \ If the \prm{index} is non positive or $>n$ then the macro expands to nothing (|{}|). +% \end{itemize} +% +% \end{ltxsyntax} +% +% \StopEventually{ +% } +% +% \part*{\LaTeX{} code} +% \addtocontents{toc}{\protect\contentsline{part}{\large\LaTeX{} code}{}{}} +% +% \section{Implementation} +% +% \subsection{Package identification} % % \begin{macrocode} %<*package> @@ -210,8 +626,8 @@ and etextools-examples.tex % % \subsection{Requirements} % -% This package requires both the \sty{etex} package by David Carlisle and -% the \sty{etoolbox} package by Philipp Lehman. +% This package requires the packages \sty{etex} package by David Carlisle and +% \sty{etoolbox} by Philipp Lehman. % % \begin{macrocode} \RequirePackage{etex,etoolbox} @@ -226,40 +642,12 @@ and etextools-examples.tex \catcode`\ =10 % \end{macrocode} % -% \subsection{Acknowledgements -- Thank You !} -% -% Thanks to Philipp Lehman for the \sty{etoolbox} package (and also for this nice class of documentation). -% Much of my work on lists are based on his work and package. -% -% Thank to Heiko Oberdiek who has done so much for the \TeX\ and \LaTeX\ community, and allows me to -% produce a package in one only \sty{.dtx} file. -% -% \subsection{Hint for the reader} -% -% Every command provided in this \sty{etextools} package are fully expandable -% unless explicitly specified. As it (one of) the philosophy of \sty{etoolbox} -% to make the most of its commands fully expandable (and this is very useful for package -% writing and/or document-style programming) the \FE fully expandable commands -% have a special sign in the margin (displayed here for information). -% -% Remain what a control sequence, a control word and a control character are... -% -% \iffalse The commands have been (extensively, more or less) tested.\fi -% -% -% \part*{User commands} -% \addtocontents{toc}{\protect\contentsline{part}{\large User commands}{}{}} -% -% \section{A few (\texorpdfstring{\oldstylenums{7}}{7}) ``helper'' macros} -% -% \begin{ltxsyntax} -% -% \cmditem{ettl@afterelse} \cmdlabel{ettl@afterelse} -% \cmditem*{ettl@afterfi} \cmdlabel{ettl@afterfi}\hfil\par -% -% Those two commands\FE are the copies of |\bbl@afterelse| and |\bbl@afterfi| from the \sty{babel} package. -% They allow to get out of |\if|...|\fi| conditionals. +% \subsection{A few (7) ``helper'' macros} % +% \iffalse +% +%% A few helper macros +% \fi % \begin{macrocode} \long\def\ettl@afterelse#1\else#2\fi{\fi#1} \long\def\ettl@afterfi#1\fi{\fi#1} @@ -267,20 +655,34 @@ and etextools-examples.tex \long\def\ettl@afterelsefi#1\else#2\fi\fi{\fi#1} % \end{macrocode} % -% {\rmk Those commands are used in \cmdref{iffirstchar} and \cmdref{expandnext} } +% \begin{macro}{\ettl@cdr} +% {\rmk \cmd{ettl@cdr} is only used in \cmdref{ifsinglechar}} +% \begin{macrocode} +\begingroup\catcode`\|=4 +\long\gdef\ettl@cdr#1#2|{#2} +\endgroup +% \end{macrocode} +% \end{macro} +% +% \iffalse +% +% \fi % -% \cmditem*{@gobblescape}\hfil\par +% \begin{macro}{\@gobblescape} % -% This sequence\FE of command is very often used, even in \sty{latex.ltx}. So +% This sequence of command is very often used, even in \sty{latex.ltx}. So % it appears to be better to put it in a macro. It's aim is to reverse the % mechanism of |\csname|...|\endcsname|: % \begin{macrocode} \newcommand*\@gobblescape{\expandafter\@gobble\string} % \end{macrocode} +% {\rmk May be we could do better, testing first if the next token is a control sequence...} +% \end{macro} +% % -% \cmditem{str@gobblescape}{string}\hfil\par +% \begin{macro}{\str@gobblescape} % -% With \FE \eTeX\space |\detokenize| it is now possible to invoke a |\string| on an arbitrary +% With \eTeX{} |\detokenize| it is now possible to invoke a |\string| on an arbitrary % sequence of tokens. Unfortunately, |\detokenize| adds a % space tokens at the very end of the sequence. |\str@gobblescape| acts exactly % the same way as |\@gobblescape| \ie it removes the first character from a string, but removes @@ -290,165 +692,108 @@ and etextools-examples.tex \newcommand\str@gobblescape[1]{\expandafter\deblank\expandafter{% \expandafter\@gobble\detokenize{#1}}} % \end{macrocode} +% \end{macro} % -% The \cmdref{deblank} command will be desbribed later. -% -% \end{ltxsyntax} -% -% \section{Expansion control} -% -% NOTA BENE: Pay attention\dbend that the expansion control macros are not \emph{primitives}! -% Therefore: -% \begin{tabbing} -% \qquad\= |\expandafter\controlsequence\noexpandcs{|\prm{csname}|}|\\ -% \> |\expandafter\controlsequence\expandonce{|\prm{command}|}| -% \end{tabbing} -% etc. etc. may not lead to the result you expected. -% The |\expandonce| macro from \sty{etoolbox} worth the same warning. -% -% For expansion control, it's better to use primitives, unless you clearly knows what -% you do and what will happen... \textbf{In particular,\dbend you'd very better avoid to use -% expansion control macros at the very beginning of the definition of a command, for if this command -% is preceded (in the user's code) by \sty{\textbackslash expandafter}, you will be lead -% to undesirable result and most probably to an error !} - -% \begin{ltxsyntax} % -% \cmditem{noexpandcs}{csname} +% \subsection{Expansion control} % -% In an \FE expansion context (|\edef|) we often want a control sequence whose name results -% from the expansion of some macros and/or other tokens to be created, but not expanded at that point. -% Roughly:§ -% \qquad |\edef{\noexpandcs{}}|§ -% will expand to: |\"cs-name"| but this (new) control sequence itself will not be expanded. -% A typical use is shown in the following code:§ -% \smex |\edef\abc{\noexpandcs{abc@\@gobblescape\controlword}}|§ -% \smex if equivalent to:\quad|\def\abc{\abc@controlword}|. % +% \begin{macro}{\noexpandcs}\cmdlabel{impl:noexpandcs} +% {\rmk|\noexpandcs| may be abbreviated f.ex. in |\`#1`| or |\"#1"| in |\edef| that take place in a group.}\seedesc{noexpandcs} % \begin{macrocode} \newcommand*\noexpandcs[1]{\expandafter\noexpand\csname #1\endcsname} % \end{macrocode} +% \end{macro} % -% {\rmk|\noexpandcs| can be abbreviated in |\`#1`| in |\edef| that take place in a group. } -% -% \cmditem{noexpandafter}\hfil\par -% -% |\noexpandafter|\FE only means |\noexpand\expandafter| and is shorter to type. -% +% \begin{macro}{\noexpandafter}\cmdlabel{impl:noexpandafter} +% {\rmk \cmd{noexpandafter} only means \cmd{noexpand}\cmd{expandafter} and is shorter to type.}\seedesc{noexpandafter} % \begin{macrocode} \newcommand\noexpandafter{\noexpand\expandafter} -% \end{macrocode} -% -% {\rmk This command is used in the definition of \cmdref{DeclareCmdListParser}.} -% \iffalse -% \cmditem{afterexpandafter} -% -% |\afterexpandafter|\FE means to delay the expansion twice :§ -% \qquad |\afterexpandafter\a\expandafter\b\c|\quad will replace |\c| by its \prm{replacement text}, then -% expand place |\b| before and replace it by its \prm{replacement text} as well, eventually consuming its -% parameters, and after that, place |\a| before the whole thing; then expansion goes further. -% -% \begin{macrocode} -% \newcommand\afterexpandafter{\expandafter\expandafter\expandafter} -% \end{macrocode} -% \fi -% -% \cmditem{expandnext}{cstoken}{first parameter of cstoken} \cmdlabel{expandnext} -% -% We\FE often want a control sequence to be expanded after its first argument. For example, if we want to test if a command -% |\foo| has a blank replacement text we will type : -% -% \qquad |\expandafter\ifblank\expandafter{\foo}| -% -% Now suppose you wish to define a macro |\detokenizecs{|\prm{csname}|}| that expands to the detokenized content -% of |\csname |\prm{csname}|\endcsname|. Without |\expandnext| you will have to say: -% \begin{tabbing} -% \qquad\= |\expandafter\expandafter\expandafter\detokenize| \\ -% \> |\expandafter\expandafter\expandafter{\csname |\prm{csname}|\endcsname}| -% \end{tabbing} -% \textbf{six} \cmd{expandafter}(s). With |\expandnext| you will just have to say:§ -% \qquad|\expandnext\expandnext\detokenize{\csname #1\endcsname}| -% -% Now observe the following game : -% \begin{tabbing} -% \qquad\= |\def\foo{foo}| \qquad \= \smex \qquad \= |\def\Foo{\foo}| \quad \= \eol \\ -% \> |\def\\FOo{\Foo}| \> \smex \> |\def\FOO{\FOo}| \> \eol \\ -% \> |\def\FOOL{\FOO}| -% \end{tabbing} -% And {\bfseries guess how many \cmd{expandafter} you will need in order to test ``|\ifblank{foo}|'' directly from |\FOOL| ??? } +% \end{macrocode} +% +% \end{macro} % -% |\expandnext| solves this problem : |\FOOL| has 5 degrees of expansion until it expands to ``foo'', so one require exactly 5 -% |\expandnext| : the solution is : +% \begin{macro}{\expandnext}\cmdlabel{impl:expandnext} % -% \qquad |\expandnext\expandnext\expandnext\expandnext\expandnext\ifblank{\FOOL}| +% This code is not properly \seedesc{expandnext} tricky but if you're eager to understand the job of each expandafter, +% it's best to go straight at the log. % -% And now : if you define, say : |\csdef{bloody fool}{\FOO}| you just require 2 more |\expandnext| in order -% to test ``foo'' from ``|\csname bloody fool\endcsname|'' ! \emph{just test it!} +% Note that the first argument of |\expandnext| must be a single \prm{cstoken} (for \cmd{expandafter} acts +% only on the first following token). % +% \iffalse +% +%% \expandnext : expansion control +%% level 1 : \expandnext#1{...} <=> \expandafter#1\expandafter{...} +%% level 2 : \expandnext\expandnext#1{...} etc. +% \fi % \begin{macrocode} \newcommand\expandnext[2]{% \ifx#1\expandnext \ettl@afterelse\expandafter\expandafter\expandafter - \expandafter\@expandnext{#2}{\expandafter\expandafter\expandafter} - \else\ettl@afterfi\expandafter#1\expandafter{#2} + \expandafter\@expandnext{#2}{\expandafter\expandafter\expandafter}% + \else\ettl@afterfi\expandafter#1\expandafter{#2}% \fi} \long\def\@expandnext#1#2#3{% \ifx#1\expandnext \expandafter\ettl@afterelse\expandafter\expandafter\expandafter - \expandafter\@expandnext{#3}{\expandafter#2#2} + \expandafter\@expandnext{#3}{\expandafter#2#2}% \else - \expandafter\ettl@afterfi#2#1#2{#3} + \expandafter\ettl@afterfi#2#1#2{#3}% \fi} % \end{macrocode} +% \end{macro} +% \iffalse +% +% \fi % -% This code is not very tricky but difficult to explain. The better is to watch at the log if the reader is eager -% to understand the job of each \cmd{expandafter}. -% -% Note that the first argument of |\expandnext| must be a single \prm{cstoken} (for \cmd{expandafter} acts -% only on the first following token). -% -% \end{ltxsyntax} -% -% \section{String manipulation} -% -% \subsection{String trimming} % -% \begin{ltxsyntax} +% \subsection{String manipulation} % -% \cmditem{deblank}{string} \cmdlabel{deblank} +% \begin{macro}{\deblank} \cmdlabel{impl:deblank} % -% The macro \FE |\deblank| will remove the extra blank space inserted by |\detokenize| at the -% very end of the \prm{string}. Actually, it removes all trailing spaces (charcode 32, catcode 10) -% from its argument: +% Note that the leading spaces \seedesc{deblank}are automatically removed by \TeX's mastication mechanism. % % \begin{macrocode} \newcommand\deblank{} -\begingroup\catcode`\&=3% a & as a math shift -\long\gdef\deblank#1{\@deblank#1 &} -\long\gdef\@deblank#1 #2&{\ifblank{#2}{#1}{#1\@deblank#2 &}} -\endgroup +\newcommand\ifempty{} +\begingroup\catcode`\|=4% a | as a tab array +\long\gdef\deblank#1{\@deblank#1 |} +\long\gdef\@deblank#1 #2|{\ifblank{#2}{#1}{#1\@deblank#2 |}} +% \end{macrocode} +% \end{macro} +% +% \iffalse +% +%% \ifempty{ text }{ true }{ false } +% \fi +% \begin{macro}{\ifempty} \cmdlabel{impl:ifempty} +% |\ifempty| is amazing because the code is so concise!\seedesc{ifempty} +% \begin{macrocode} +\long\gdef\ifempty#1{\csname @\ifx|#1|first\else second\fi oftwo\endcsname} +\endgroup% catcode group % \end{macrocode} +% \end{macro} +% \iffalse +% +% \fi % -% Note, by the way, that the leading spaces are also removed by \TeX's mastication mechanism. % \goodbreak % % \subsection{Expanded string comparison} % -% \cmditem{xifblank}{string}{true}{false} -% -% |\xifblank| is similar to |\ifblank| except that the \prm{string} is first expanded -% with |\protected@edef|: +% \begin{macro}{\xifblank}\cmdlabel{impl:xifblank} +% Just expands the parameter using |\protected@edef| before testing for |\ifblank|: \seedesc{xifblank} % \begin{macrocode} \newrobustcmd\xifblank[1]{\begingroup \protected@edef\@xifblank{\endgroup \noexpand\ifblank{#1}% }\@xifblank} % \end{macrocode} +% \end{macro} % -% \cmditem{xifstrequal}{string1}{string2}{true}{false} -% -% In the same way, |\xifstrequal| is similar to |\ifstrequal| but both \prm{string} arguments -% are expanded with |\protected@edef| before comparison: +% \begin{macro}{\xifstrequal}\cmdlabel{impl:xifstrequal} +% Same idea: protected expansion before testing: \seedesc{xifstrequal} % \begin{macrocode} \newrobustcmd\xifstrequal[2]{% \begingroup\protected@edef\@tempa{#1}\protected@edef\@tempb{#2}% @@ -456,30 +801,10 @@ and etextools-examples.tex \else \aftergroup\@secondoftwo \fi\endgroup} % \end{macrocode} +% \end{macro} % -% \subsection{Testing characters} -% -% \cmditem{iffirstchar}{string1}{string2}{true}{false} \cmdlabel{iffirstchar} -% \cmditem*{iffirstchar}{}{string}{true}{false} -% -% |\iffirstchar| will\FE compare the character codes of the \textbf{first} characters of each \prm{string}. The -% comparison is \emph{catcode agnostic} and the macro is fully expandable. Neither \prm{string1} not \prm{string2} -% is expanded before comparison. -% -% There is a ``special'' use of this command when the user want to test if a \prm{string} begins -% with an \emph{escape} character (\,\textbackslash\,) one may say: -% \begin{tabbing} -%\qquad\= |\iffirstchar \@backslashchar{|\prm{string}|}|\qquad\= or even easier:\\ -% \>|\iffirstchar {}{|\prm{string}|}| -% \end{tabbing} -% Please note that the tests: -% \begin{tabbing} -% \qquad\qquad\=|\iffirstchar |\=|{|\prm{whatever string1 is}|}{}|\\ -% and:\>|\iffirstchar |\>|{}{}| -% \end{tabbing} -% are \textbf{always expanded into \underline{\prm{false}}} -% (for consistency with the shortcut-test for |\@backslashchar|): -% +% \begin{macro}{\iffirstchar}\cmdlabel{impl:iffirstchar} +% |\iffirstchar| test if |#1| and |#2| begins with the same character. \seedesc{iffirstchar} % \begin{macrocode} \newcommand\iffirstchar[2]{% \if \expandafter\@car\string#2\relax\@nil\expandafter\@car#1\string\\\@nil @@ -487,21 +812,24 @@ and etextools-examples.tex \else \expandafter\@secondoftwo \fi} % \end{macrocode} +% \end{macro} % -% -% \cmditem{ifsinglechar}{string1}{string2}{true}{false} \cmdlabel{ifsinglechar} -% -% |\ifsinglechar|\FE will perform the test |\iffirstchar| but will also check that \prm{string2} has only one character. -% +% \begin{macro}{\ifsinglechar}\cmdlabel{impl:ifsinglechar} +% Test if |#2| is a single character equal to |#1|: \seedesc{ifsinglechar} % \begin{macrocode} -\newcommand\ifsinglechar[2]{% +\newcommand\ifsinglechar{} +\begingroup\catcode`\|=4 +\long\gdef\ifsinglechar#1#2{% % \end{macrocode} % % \begin{codecomment} % Remember that neither \prm{string1} nor \prm{string2} is expanded.§ % First: test if |#2| is a single character: % \begin{macrocode} - \expandnext\expandnext\ifblank{\expandafter\@cdr\string#2 \@nil} + \csname @\expandafter\expandafter\expandafter\ifx + \expandafter\expandafter\expandafter|% + \expandafter\ettl@cdr\string#2||first\else second\fi + oftwo\endcsname % \end{macrocode} % The test returned \prm{true}: therefore test further the character codes of |#2| and |#1|, and % switch to \prm{true} only in case of equality: @@ -511,107 +839,51 @@ and etextools-examples.tex % Otherwise, switch to \prm{false} % \begin{macrocode} \@secondoftwo} +\endgroup% catcode group % \end{macrocode} % \end{codecomment} +% \end{macro} % -% Now with the macro |\ifsinglechar| it becomes possible to write fully expandable macros with an option, \textbf{provided -% that this macro has at least one non-optional argument}, as far as we don't use |\futurelet| nor any assignation. -% The ``trick'' is the following: -% \begin{tabbing} -% \qquad\= |\def\MacroWithOption#1{\ifsing|\=|lechar|\=|[{#1}| \\ -% \>\>|{\MacroHasOption[}| \\ -% \>\>|{\MacroNoOption{#1}}}}|\\ -% \> |\def\MacroHasOption[#1]#2|... \>\textit{definition} \\ -% \> |\def\MacroNoOption#1|...\>\textit{definition} -% \end{tabbing} -% -% Moreover (in the style of |\@testopt|): -% \begin{tabbing} -% \qquad\= |\def\MacroWithOption#1{\ifsing|\=|lechar|\=|[{#1}|\\ -% \>\>|{\MacroHasOption#1}|\\ -% \>\>|{\MacroHasOption[default]{#1}}}| -% \end{tabbing} -% -% Therefore, the following macro is defined: -% -% \subsection{Fully expandable macros with options} -% -% \cmditem{FE@testopt}{argument to be tested}{commands}{default option} \cmdlabel{FE@testopt} -% -% |\FE@testopt| mimics the behaviour of |\@testopt| but is Fully Expandable (\sty{FE})\FE and can be used as follow:§ -% \qquad |\def\MacroWithOption#1{\FE@testopt{#1}\MacroHasOption{default}}|\par -% -% Remember that |\MacroWithOption| \textbf{must have at least one mandatory argument.} -% +% \iffalse +% +%%\FE@testopt{#1}{commands}{default option} +% \fi +% \begin{macro}{\FE@testopt}\cmdlabel{impl:FE@testopt} +% Fully expandable |\@testopt|-like test:\seedesc{FE@testopt} % \begin{macrocode} \newcommand\FE@testopt[3]{\ifsinglechar [{#1}{#2#1}{#2[{#3}]{#1}}} % \end{macrocode} % -% \textbf{Limitation :}\dbend if you call such an option command without option and with |{[}| as mandatory -% argument, it will be considered that the command has an option, whose end will be at the next `\,]\,' found in the input string. -% -% {\rmk |\FE@testopt| is used in the definition of \cmdref{DeclareCmdListParser}.} -% -% \cmditem{FE@ifstar}{argument to be tested}{star-commands}{non-star commands} \cmdlabel{FE@ifstar} -% -% Similarly,\FE it becomes possible to mimic the behaviour of |\@ifstar| but in a fully expandable(\sty{FE}) way. -% |\FE@ifstar| can be used as follow :§ -% \begin{tabbing} -% \qquad\= |\def\StarOrNotCommand#1{\FE@|\=|ifstar|\=|{#1}|\\ -% \>\>|{\StarredCommand}|\\ -% \>\>|{\NotStarredCommand}}| -% \end{tabbing} -% -% Remember that |\StarredCommand| and |\NotStarredCommand| \textbf{must have at least one mandatory argument.} +% \end{macro} % +% \iffalse +% +%%\FE@ifstar{#1}{\StarredMacro}{\NotStarredMacro} +% \fi +% \begin{macro}{\FE@ifstar}\cmdlabel{impl:FE@ifstar} +% Fully expandable |\@ifstar|-like test:\seedesc{FE@ifstar} % \begin{macrocode} \newcommand\FE@ifstar[3]{\ifsinglechar *{#1}{#2}{#3{#1}}} % \end{macrocode} % -% \textbf{Limitation :}\dbend if you call such a command with |{*}| as mandatory argument, -% it will be considered that the command is starred, and the mandatory argument will be found next inside the input string. -% -% \textbf{This ``limitation'' is in fact a benediction:} thank to it we can have -% {\it\catcode`\ \active\let =-Fully Expandable starred macros with option\/}!\nobreak -% {\rmk |\FE@ifstar| is used in the definitions of \cmdref{DeclareCmdListParser}, \cmdref{csvloop}, \cmdref{listloop} -% and \cmdref{csvtolist}.} -% \goodbreak -% \end{ltxsyntax} -% -% \section{List management} -% -% \subsection{The Command-List Parser} -% -% The \sty{etoolbox} package provides a way to define list parsers a fully expandable macros: -% the list parser is able to expand the auxiliary command |\do| on each item of a list. +% \end{macro} % \iffalse -% Declaration of a list parser is done via the |\DeclareListParser| macro\footnotemark. -% \footnotetext{besides, \sty{etoolbox} defines the \sty{\textbackslash docsvlist} and the -% \sty{\textbackslash dolistloop} macros: the choice of this name is not very friendly -% and we expected to have a \sty{\textbackslash docsvloop} macro instead...}. +% % \fi % -% Here we provide a |\DeclareCmdListParser| macro that is compatible and slightly different, because the auxiliary -% command is not necessarily |\do|. Such a command-list-parser is fully expandable. -% -% The idea is that if |\csvloop| has been defined as a command-parser then, thank to the fully expandable macro |\FE@testopt| -% we can call for expansion: -% \begin{tabbing} -% \qquad\= |\csvloop*{item,item,...}|\,\= as a shortcut for\,\= |\csvloop*[\do]{item,...}|\\ -% or:\> |\csvloop*[\listadd\mylist]{item,item,...}|\quad -% \end{tabbing} -% for example to convert the csv-list into internal \sty{etoolbox} list. -% -% {\rmk The star-form of \cmdref{csvloop} will be explained below.} -% -% \begin{ltxsyntax} +% \goodbreak % -% \cmditem{DeclareCmdListParser}{command}{separator} \cmdlabel{DeclareCmdListParser} +% \begin{macro}{\DeclareCmdListParser}\cmdlabel{impl:DeclareCmdListParser} % -% |\DeclareCmdListParser| acts in the same way as \sty{etoolbox}-|\DeclareListParser| and the command-list-parser +% |\DeclareCmdListParser|\seedesc{DeclareCmdListParser} acts in the same way as +% \sty{etoolbox}-|\DeclareListParser| and the command-list-parser % are sensitive to the category code of the \prm{separator} -% {\catcode`\ =13\let =-\it(which is not necessarily a single character and shall not be a {\tt\&} with a catcode of 3)}. % +%% \iffalse +% +%% \DeclareCmdListParser : general constructor for command-list parsers +%% \DeclareCmdListParser\ParserName{separator} +% \fi % \begin{codecomment} % The command-list-parser will be defined only if it is definable: % @@ -625,7 +897,7 @@ and etextools-examples.tex % and globally define the macro inside a purposeful group: % % \begin{macrocode} -\begingroup\catcode`\&=3 +\begingroup\catcode`\&=3\catcode`\`=3 \gdef\etextools@defcmdparser#1#2{% \begingroup \def\`##1`{\expandafter\noexpand\csname ##1\endcsname}% @@ -697,97 +969,88 @@ and etextools-examples.tex \endgroup % \end{macrocode} % \end{codecomment} +% \end{macro} +% \iffalse +% +% +%% \csvloop[\command]\csvListMacro +%% \csvloop*[\command]{item,item,item} +% \fi % -% \subsection{Loops into lists} -% -% Now we have to declare two command-list-parsers : |\listloop| for \sty{etoolbox} lists -% and |\csvloop| for comma-separated lists. -% -% \cmditem{csvloop}[auxiliary commands]{csvlistmacro} \cmdlabel{csvloop} -% \cmditem*{csvloop*}[auxiliary commands]{item,item,item,...} -% \cmditem*{listloop}[auxiliary commands]{listmacro} \cmdlabel{listloop} -% \cmditem*{listloop*}[auxiliary commands]{expanded list} -% -% |\listloop|\FE acts exactly as \sty{etoolbox}-|\dolistloop| with an optional argument to change -% the default auxiliary command |\do| to apply to each item of the list : -% \begin{tabbing} -% \qquad\=|\listloop\mylist|\;\=\textit{is}\;\= |\listloop[\do]\mylist|\;\=\textit{and is also}\;\= |\dolistloop\mylist|\\ -% \> |\csvloop\csvlist|\> \textit{is}\> |\csvloop[\do]\csvlist|\> \textit{and is also}: \eol \\ -% \>\>\> |\expandafter\docsvlist\expandafter{\csvlist}| -% \end{tabbing} -% Definition of |\csvloop| : +% \begin{macro}{\csvloop}\cmdlabel{impl:csvloop} +% Definition of |\csvloop|:\seedesc{csvloop} % \begin{macrocode} \DeclareCmdListParser\csvloop{,} % \end{macrocode} +% \end{macro} % % \begin{codecomment} % Definition of |\listloop| (with a `\,\textbar\,' of catcode 3 -- cf.\sty{etoolbox}): % \begin{macrocode} \begingroup\catcode`\|=3 - \gdef\do{\DeclareCmdListParser\listloop{|}\undef\do}\aftergroup\do -\endgroup + \def\do{\DeclareCmdListParser\listloop{|}}% +\expandafter\endgroup\do % \end{macrocode} % \end{codecomment} % -% \subsection{Converting csv lists to \sty{etoolbox}-lists} -% -% \cmditem{csvtolist}{listmacro}{csvlistmacro} \cmdlabel{csvtolist} -% \cmditem*{csvtolist*}{listmacro}{item,item,item...} -% -% |\csvtolist| converts a comma separated list into an internal \sty{etoolbox} list. It is useful to insert more than one item -% at a time in a list. Those macros are not fully expandable because of the redefinition of \prm{listmacro} done by |\listadd|... -% -% It's also the first application of the \cmdref{csvloop} macro just defined: % +% \iffalse +% +%%\csvtolist\csvListMacro +%%\csvtolist*{item,item,item} +% \fi +% \begin{macro}{\csvtolist}\cmdlabel{impl:csvtolist} +% This is the first application of |\csvloop|:\seedesc{csvtolist} % \begin{macrocode} -\newcommand\csvtolist{\@ifstar\star@csvtolist\nost@csvtolist} -\def\star@csvtolist#1{\let#1\@empty\csvloop*[{\unexpanded{\listadd#1}}]} -\def\nost@csvtolist#1{\let#1\@empty\csvloop[{\unexpanded{\listadd#1}}]} +\newcommand\csvtolist{\@ifstar\star@csvtolist\nost@csvtolist}% +\def\star@csvtolist#1{\let#1\@empty\csvloop*[{\unexpanded{\listadd#1}}]}% +\def\nost@csvtolist#1{\let#1\@empty\csvloop[{\unexpanded{\listadd#1}}]}% % \end{macrocode} +% \end{macro} % -% \cmditem{csvtolistadd}{listmacro}{csvlistmacro} \cmdlabel{csvtolistadd} -% \cmditem*{csvtolistadd*}{listmacro}{item,item,item...} -% -% |\csvtolistadd| acts similarly but does not reset the \prm{listmacro} to |\@empty|: -% +% \iffalse +% +%%\csvtolistadd\csvListMacro +%%\csvtolistadd*{item,item,item} +% \fi +% \begin{macro}{\csvtolistadd}\cmdlabel{impl:csvtolistadd} +% It's quite the same\seedesc{csvtolistadd} as the latter except it does not +% reset the list to empty at the very beginning: % \begin{macrocode} -\newcommand\csvtolistadd{\@ifstar\star@csvtolistadd\nost@csvtolistadd} +\newcommand\csvtolistadd{\@ifstar\star@csvtolistadd\nost@csvtolistadd}% \def\star@csvtolistadd#1#2{\ifblank{#2} - {\let#1\@empty}{\csvloop*[{\unexpanded{\listadd#1}}]{#2}}} + {\let#1\@empty}{\csvloop*[{\unexpanded{\listadd#1}}]{#2}}}% \def\nost@csvtolistadd#1#2{\ifblank{#2} - {\let#1\@empty}{\csvloop[{\unexpanded{\listadd#1}}]{#2}}} + {\let#1\@empty}{\csvloop[{\unexpanded{\listadd#1}}]{#2}}}% % \end{macrocode} +% \end{macro} % -% \end{ltxsyntax} -% -% \subsection{Removing elements from \sty{etoolbox}-lists} -% -% The \sty{etoolbox} package provides |\listadd|, |\listgadd| and |\listxadd| commands -% to add items to a list. However, no command is designed to remove an element from a -% list. -% -% \begin{ltxsyntax} -% -% \cmditem{listdel}{listmacro}{item} \cmdlabel{listdel} -% \cmditem*{listgdel}{listmacro}{item} \cmdlabel{listgdel} -% \cmditem*{listxdel}{listmacro}{item} \cmdlabel{listxdel} -% -% The |\listdel| command removes the element \prm{item} from the list \prm{listmacro}. Note that the -% \prm{listmacro} is redefined after deletion: % +% \iffalse +% +%%\listdel\listMacro{item} +%%\listgdel\listMacro{item} +%%\listedel\listMacro{item} +%%\listxdel\listMacro{item} +% \fi +% \begin{macro}{\listdel}\cmdlabel{impl:listdel} +% |\listdel| removes an item from a list:\seedesc{listdel} % \begin{macrocode} -\newrobustcmd\listdel[2]{\@listdel\def{#1}{#2}} +\newrobustcmd\listdel[2]{\@listdel\def{#1}{#2}}% % \end{macrocode} +% \end{macro} % -% Commands |\listgdel| and |\listxdel| are similar, except that the assignment (\ie the redefinition -% of the list) is global; for the latter, the \prm{item} is first expanded using |\protected@edef|: % % \begin{macrocode} -\newrobustcmd\listgdel[2]{\@listdel\gdef{#2}{#2}} +\newrobustcmd\listgdel[2]{\@listdel\gdef{#1}{#2}}% \newrobustcmd\listxdel[2]{\begingroup \protected@edef\@listxdel{\endgroup - \unexpanded{\@listdel\gdef#1}{#2}% - }\@listxdel} + \unexpanded{\@listdel\gdef{#1}}{#2}% + }\@listxdel}% +\newrobustcmd\listedel[2]{\begingroup + \protected@edef\@listedel{\endgroup + \unexpanded{\@listdel\def{#1}}{#2}% + }\@listedel} % \end{macrocode} % % \begin{codecomment} @@ -795,18 +1058,19 @@ and etextools-examples.tex % We need first to be placed in an environment where the `\,\textbar\,' delimiter has a category code of 3 % (cf \sty{etoolbox}-lists definitions): % \begin{macrocode} - \begingroup\catcode`\|=3\catcode`\&=3 +\begingroup\catcode`\|=3\catcode`\&=3 % \end{macrocode} % Inside this ``catcode-group'' the definition of |\@listdel| ought to be global: % \begin{macrocode} - \long\gdef\@listdel#1#2#3{% +\long\gdef\@listdel#1#2#3{% % \end{macrocode} % \qquad |#1|=|\def| or |\gdef|, |#2|=\prm{listmacro}, |#3|=\prm{item} to remove.\par % In order to preserve the hash-table from temporary definitions, a group is opened: % \begin{macrocode} - \begingroup +\begingroup \def\@tempa##1|#3|##2&{##1|##2\@tempb}% % \end{macrocode} +% % |\@tempa| is a delimited macro whose aim is to remove the first \prm{item} found in the list % and it adds |\@tempb| after the result. If the \prm{item} was not in the list, then |##2| % will be empty. Note that |\@tempa| is the only macro whose definition depends on the \prm{item} @@ -841,7 +1105,7 @@ and etextools-examples.tex % \begin{macrocode} \expandafter\@tempx\unexpanded\expandafter{#2}&}% % \end{macrocode} -% Then just expand |\@redef| (fully expandable): +% Then just expand |\@redef| to proceed the redefinition of \prm{listmacro}: % \begin{macrocode} }\@redef}% end of \@listdel % \end{macrocode} @@ -850,43 +1114,28 @@ and etextools-examples.tex \endgroup % \end{macrocode} % \end{codecomment} -% \end{ltxsyntax} -% -% \subsection{Index of an element in a list} % -% \begin{ltxsyntax} +%\iffalse +% +% +%% \getlistindex (result in \indexinlist) +% \fi % -% \cmditem{getlistindex}{item}{listmacro} \cmdlabel{getlistindex} -% \cmditem*{xgetlistindex}{item}{listmacro} \cmdlabel{xgetlistindex} -% \cmditem*{getlistindex*}{item}{list} -% \cmditem*{xgetlistindex*}{item}{list} % -% Sometimes it is interesting to know at which offset in a list lies a given item. |\getlistindex| answers to this question. -% |\xgetlistindex| does the same thing but expand the \prm{item} (using |\protected@edef|) prior looking for it in the list. -% The result (\ie the position of \prm{item} in \prm{list}) is stored in |\indexinlist|. -% \begin{itemize} -% \item \ If \prm{item} is not found in the \prm{list} then |\indexinlist| is 0 -% \item \ If \prm{item} is found in first position then |\indexinlit| is 1 and so on. -% \end{itemize} +% \begin{macro}{\getlistindex}\cmdlabel{impl:getlistindex} +% \cmd{getlistindex} may be defined, with its star form (no expansion of the list)\seedesc{getlistindex} +% and normal form (\prm{listmacro} expanded once); +% The search-index is initialised at 1: % -% As for the command-list-parser, the star versions are designed in case the list (in the second argument) is already expanded. -% \begin{codecomment} % We first need to get into a group where delimiter `\,\textbar\,' and `\,\&\,' have catcode 3: % \begin{macrocode} \begingroup\catcode`\|=3\catcode`\&=3 -% \end{macrocode} -% The next two macros expands to the first item in a list or the remainder of the list respectively : -% \begin{macrocode} -\gdef\ettl@list@first@item#1|#2&{#1} -\gdef\ettl@list@other@item#1|#2&{#2} -% \end{macrocode} -% |\getlistindex| may be defined, with its star form (no expansion of the list) and normal form (\prm{listmacro} expanded once); -% The search-index is initialised at 1: -% \begin{macrocode} \gdef\getlistindex#1{\FE@ifstar{#1}{\ettl@getlistindex{}} {\ettl@getlistindex\expandnext}} % \@ifstar{\ettl@getlistindex{}}{\ettl@getlistindex{\expandnext}}} % \end{macrocode} +% \end{macro} +% % |\xgetlistindex| is similar with prior expansion of \prm{item}: % \begin{macrocode} \gdef\xgetlistindex#1{\FE@ifstar{#1}{\ettl@xgetlistindex{}} @@ -895,7 +1144,9 @@ and etextools-examples.tex \protected@edef\next{\endgroup\unexpanded{\ettl@getlistindex{#1}{#2}}{#3}% }\next} % \end{macrocode} +% % Then the following macro does the job in a loop, which is not fully expandable because the use of |\ifstrequal|: +% % \begin{macrocode} \gdef\ettl@getlistindex#1#2#3{\begingroup#1\ettl@get@list@idx{#3}{#2}{\numexpr1}} \gdef\ettl@get@list@idx#1#2#3{% #1=expanded list, #2=item, #3=index @@ -903,26 +1154,20 @@ and etextools-examples.tex {\expandnext\ifstrequal{\ettl@list@first@item#1&}{#2} {\endgroup\edef\indexinlist{\number#3\relax}} {\expandnext\ettl@get@list@idx{\ettl@list@other@item#1&}{#2}{#3+1}}}} +% \end{macrocode} +% +% \begin{codecomment} +% The next two macros expand to the first item in a list or the remainder of the list respectively : +% \begin{macrocode} +\gdef\ettl@list@first@item#1|#2&{#1} +\gdef\ettl@list@other@item#1|#2&{#2} \endgroup% catcode group % \end{macrocode} % \end{codecomment} -% \end{ltxsyntax} -% -% \subsection{Extract by index from a list} -% -% \begin{ltxsyntax} -% -% \cmditem{getlistitem}{listmacro}{index [numexpr expression]} \cmdlabel{getlistitem} -% \cmditem*{getlistitem*}{list}{index} % -% Now\FE the reverse operation of ``getting the index'' is ``getting the element'' whose index is known. Note that this macro -% is fully expandable for we don't have to compare the items (just count the loop using |\numexpr| -- no counter). Therefore we use the -% fully expandable version of |\ifstar| : \cmdref{FE@ifstar} to keep the ``fully-expand-ability'' of the star-form as well: -% \begin{itemize} -% \item \ If the \prm{index} is in the range $[1\dots n]$ then the macro expands to \prm{item}$_n$ -% \item \ If the \prm{index} is non positive or $>n$ then the macro expands to nothing (|{}|). -% \end{itemize} % +% \begin{macro}{\getlistitem}\cmdlabel{impl:getlistitem} +% \strut\seedesc{getlistitem} % \begin{macrocode} \newcommand\getlistitem[1]{\FE@ifstar{#1}\ettl@getlistitem {\expandnext\ettl@getlistitem}} @@ -938,6 +1183,7 @@ and etextools-examples.tex \fi\fi}} \endgroup % \end{macrocode} +% \end{macro} % % \end{ltxsyntax} % @@ -945,7 +1191,7 @@ and etextools-examples.tex % % \end{macrocode} % -% \section{Example} +% \subsection{Example} % % \begin{macrocode} %<*example> @@ -998,6 +1244,21 @@ and etextools-examples.tex \section{\cmd{expandnext} examples} +\subsection{Test if the replacement text of macro is really empty} + +\def\xx{ } +\def\testexpandnext{% + \edef\expandnextTest{\string\xx\ is \expandnext\ifempty{\xx}{}{not} empty} +} +\preline\xx +\test{expandnext} + +\def\xx{} +\preline\xx +\test{expandnext} + + +\clearpage \subsection{Test if the replacement text of a macro is blank (empty or spaces)} \def\xx{something} @@ -1011,7 +1272,8 @@ and etextools-examples.tex \preline\xx \test{expandnext} -\clearpage + + \subsection{Detokenize the replacement text of a named-sequence} \def\detokenizecs#1{\expandnext\expandnext\detokenize{\csname #1\endcsname}} \def\testexpandnext{% @@ -1027,6 +1289,17 @@ and etextools-examples.tex }\hrulefill\par \test{ifsinglechar} +\def\testifsinglechar{% + \edef\ifsinglecharTest{\ifsinglechar *{ *}{ single star }{ something else }} +}\hrulefill\par +\test{ifsinglechar} + +\def\testifsinglechar{% + \edef\ifsinglecharTest{\ifsinglechar *{ * }{ single star }{ something else }} +}\hrulefill\par +\test{ifsinglechar} +{\small Note the space \textbf{after} the star $\uparrow$.} + \def\testiffirstchar{% \edef\iffirstcharTest{\iffirstchar *{*hello*}{ first char is star }{ something else }} }\hrulefill\par @@ -1034,8 +1307,8 @@ and etextools-examples.tex \subsection{Fully Expandable starred macros} \def\starmacro#1{\FE@ifstar{#1}\starred\notstarred} -\def\starred#1{your "#1" will be processed by the STAR form} -\def\notstarred#1{your "#1" will be processed by the NORMAL form} +\def\starred#1{your "#1" will be processed by the STAR form} +\def\notstarred#1{your "#1" will be processed by the NORMAL form} \def\testFE@ifstar{% \edef\FE@ifstarTest{\starmacro{sample text}}} \preline\starmacro @@ -1083,7 +1356,7 @@ and etextools-examples.tex \preline\mylist \preline*\BySeven \test{csvloop} -\subsubsection{protected \cmd{testbf}} +\subsubsection{protected \cmd{textbf}} \def\testcsvloop{% \protected@edef\csvloopTest{\csvloop*[\textbf]{hello ,my ,friends}} }\hrulefill\par @@ -1101,29 +1374,55 @@ and etextools-examples.tex \getlistindex{four}\mylist \hrulefill\par \noindent\hskip6pt|\csvtolist*\mylist{one,two,three,four,five,alpha,beta,gamma}|\par\vskip1.5ex -\noindent\hskip6pt\textcolor{blue}{\llap\smex\cmd{getlistindex}{four}\cmd{mylist}}\par\vskip1.5ex +\noindent\hskip6pt\textcolor{blue}{\llap\smex\cmd{getlistindex}\string{four\string}\cmd{mylist}}\par\vskip1.5ex \noindent\hskip6pt\cmd{indexinlist}=\quad{\bfseries\meaning\indexinlist}\par\hrulefill\par \end{document} % % \end{macrocode} % +% \section{Revision history} +% +% \begin{changelog} +% +% \begin{release}{2z}{2009-08-12} +% \item Addition of \cmdref{ifempty} +% +% \item Modification of \cmdref{ifsinglechar}\\ +% |\ifsinglechar| now works with |\ifempty| so that:\\ +% \begin{tabbing} +% \quad\=|\macro{ * }|\quad\= is no more considered as a starred form \\ +% \>\>because of the spaces following the |*| \\ +% \>\> however, the spaces \textbf{before} are skipped, \\ +% \>\>as does |\@ifnextchar| from the \LaTeX{} kernel. +% \end{tabbing} +% +% \item Index added to this documentation paper. +% \end{release} + +% \begin{release}{2e}{2009-07-14} +% \item First version (include an example file) +% \end{release} +% +% \end{changelog} +% % \begin{thebibliography}{9} % % \bibitem{etex} % David Carlisle and Peter Breitenlohner % \textit{The \sty{etex} package}; % 1998/03/26 v2.0; -% \CTAN{macros/latex/contrib/etex-pkg/etex.sty}. +% \CTAN{macros/latex/contrib/etex-pkg/}. % % \bibitem{etoolbox} % Philipp Lehman % \textit{The \sty{etoolbox} package}; % 2008/06/28 v1.7; -% \CTAN{macros/latex/contrib/etoolbox/etoolbox.dtx}. +% \CTAN{macros/latex/contrib/etoolbox/}. % % \end{thebibliography} % +% \setcounter{IndexColumns}{2}\clearpage % \PrintIndex % % \label{LastPage} diff --git a/Master/texmf-dist/source/latex/etextools/etextools.ins b/Master/texmf-dist/source/latex/etextools/etextools.ins index 79b0985e6af..ca83a61febb 100644 --- a/Master/texmf-dist/source/latex/etextools/etextools.ins +++ b/Master/texmf-dist/source/latex/etextools/etextools.ins @@ -22,7 +22,6 @@ %% and etextools-examples.tex %% %%% etextools : more e-TeX useful tools for LaTeX package writers -%%% Florent CHERVET \input docstrip.tex \Msg{************************************************************************} \Msg{* Installation} @@ -76,6 +75,7 @@ and etextools-examples.tex \endbatchfile + \endinput %% %% End of file `etextools.ins'. -- cgit v1.2.3