From 213cf08b49d08cde4318dc8fe31f37d3a2153787 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Wed, 9 Jan 2013 00:40:33 +0000 Subject: multiexpand (8jan13) git-svn-id: svn://tug.org/texlive/trunk@28768 c570f23f-e606-0410-a88d-b1316a301751 --- Master/texmf-dist/doc/latex/multiexpand/README | 39 +++ .../doc/latex/multiexpand/multiexpand.pdf | Bin 0 -> 284328 bytes .../source/latex/multiexpand/multiexpand.dtx | 315 +++++++++++++++++++++ .../source/latex/multiexpand/multiexpand.ins | 71 +++++ .../tex/latex/multiexpand/multiexpand.sty | 56 ++++ Master/tlpkg/bin/tlpkg-ctan-check | 2 +- Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc | 1 + Master/tlpkg/tlpsrc/multiexpand.tlpsrc | 0 8 files changed, 483 insertions(+), 1 deletion(-) create mode 100644 Master/texmf-dist/doc/latex/multiexpand/README create mode 100644 Master/texmf-dist/doc/latex/multiexpand/multiexpand.pdf create mode 100644 Master/texmf-dist/source/latex/multiexpand/multiexpand.dtx create mode 100644 Master/texmf-dist/source/latex/multiexpand/multiexpand.ins create mode 100644 Master/texmf-dist/tex/latex/multiexpand/multiexpand.sty create mode 100644 Master/tlpkg/tlpsrc/multiexpand.tlpsrc diff --git a/Master/texmf-dist/doc/latex/multiexpand/README b/Master/texmf-dist/doc/latex/multiexpand/README new file mode 100644 index 00000000000..062ceda37ba --- /dev/null +++ b/Master/texmf-dist/doc/latex/multiexpand/README @@ -0,0 +1,39 @@ +Variations on the `\expandafter` TeX primitive +============================================== +* E-mail: blflatex@gmail.com +* Released under the LaTeX Project Public License v1.3c or later + See http://www.latex-project.org/lppl.txt + +Every TeX programmer knows `\expandafter`, and how messy it can become +when trying to expand several times a very deeply hidden token. For +example, say we want to expand `\C` four times before `\A` and `\B` in +`\A\B\C`. The traditional approach would be to insert 15 `\expandafter` +before `\A` and the same number before `\B`. This package allows the two +simpler codes + + \expandafter\A\expandafter\B\romannumeral\multiexpand{4}\C + +or + + \expandafter\A\romannumeral\multiexpandafter{4}\B\C + +In one step of expansion (triggered by the `\expandafter`'s), the +sequence `\romannumeral\multiexpand{4}` expands the following token 4 +times, whereas `\romannumeral\multiexpandafter{4}` expands the token +after that 4 times. + +The code behaves with braces as `\expandafter` would. Another example is + + \MultiExpandAfter{2}\a\MultiExpandAfter{3}{% + \MultiExpandAfter{10}\b\MultiExpandAfter{10}\c\d}, + +which expands `\d` 10 times, then `\c` 8 times, then `\b` once. +The whole process will only take two steps of expansion. + +The package can be built from the file `multiexpand.dtx' by running + + pdflatex multiexpand.dtx + pdflatex multiexpand.dtx + pdflatex multiexpand-example.tex + +The last step is optional: it runs a series of tests. diff --git a/Master/texmf-dist/doc/latex/multiexpand/multiexpand.pdf b/Master/texmf-dist/doc/latex/multiexpand/multiexpand.pdf new file mode 100644 index 00000000000..b6b2599f27a Binary files /dev/null and b/Master/texmf-dist/doc/latex/multiexpand/multiexpand.pdf differ diff --git a/Master/texmf-dist/source/latex/multiexpand/multiexpand.dtx b/Master/texmf-dist/source/latex/multiexpand/multiexpand.dtx new file mode 100644 index 00000000000..02740fc75f3 --- /dev/null +++ b/Master/texmf-dist/source/latex/multiexpand/multiexpand.dtx @@ -0,0 +1,315 @@ +% \iffalse meta-comment +%<*internal> +\iffalse +% +%<*readme> +Variations on the `\expandafter` TeX primitive +============================================== +* E-mail: blflatex@gmail.com +* Released under the LaTeX Project Public License v1.3c or later + See http://www.latex-project.org/lppl.txt + +Every TeX programmer knows `\expandafter`, and how messy it can become +when trying to expand several times a very deeply hidden token. For +example, say we want to expand `\C` four times before `\A` and `\B` in +`\A\B\C`. The traditional approach would be to insert 15 `\expandafter` +before `\A` and the same number before `\B`. This package allows the two +simpler codes + + \expandafter\A\expandafter\B\romannumeral\multiexpand{4}\C + +or + + \expandafter\A\romannumeral\multiexpandafter{4}\B\C + +In one step of expansion (triggered by the `\expandafter`'s), the +sequence `\romannumeral\multiexpand{4}` expands the following token 4 +times, whereas `\romannumeral\multiexpandafter{4}` expands the token +after that 4 times. + +The code behaves with braces as `\expandafter` would. Another example is + + \MultiExpandAfter{2}\a\MultiExpandAfter{3}{% + \MultiExpandAfter{10}\b\MultiExpandAfter{10}\c\d}, + +which expands `\d` 10 times, then `\c` 8 times, then `\b` once. +The whole process will only take two steps of expansion. + + +The package can be built from the file `multiexpand.dtx' by running + + pdflatex multiexpand.dtx + pdflatex multiexpand.dtx + pdflatex multiexpand-example.tex + +The last step is optional: it runs a series of tests. +% +%<*example> + \input multiexpand.sty\relax + % |\expandonce| redefines its argument |#1| as |#1| expanded once. + \long\gdef\expandonce#1{% + \long\edef#1{\unexpanded\expandafter\expandafter\expandafter{#1}}} + % Commands that expand to each other, to count how many times things + % were expanded. + \def\0{\1} \def\1{\2} \def\2{\3} \def\3{\4} \def\4{\5} + \def\5{\6} \def\6{\7} \def\7{\8} \def\8{\9} \def\9{\0x} + % We test |\MultiExpand|, which needs two expansions. In particular, we see + % that the implementation is reasonably quick, and we get the $2011$-th + % expansion of |\0|. + \long\gdef\a{\MultiExpand{2011}\0} \expandonce\a \expandonce\a + \long\gdef\b{\1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx% + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx% + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx} + \ifx\a\b\message{Correct! }\else\show\WRONG\fi + % + % Test |\MultiExpandAfter|, two expansions to get the specified expansion. + % The results also show that the expansion happens in the expected order. + \long\gdef\a{% + \MultiExpandAfter{27}\0% note that we get \5xx (25=27-2). + \MultiExpandAfter{14}\0% note that we get \2x (12=14-2). + \MultiExpandAfter{38}\0\0}% note that we get \8xxx... no "-2". + \expandonce\a \expandonce\a + \long\gdef\b{\0\5xx\2x\8xxx} + \ifx\a\b\message{Correct! }\else\show\WRONG\fi + % + % For comparison, the "Hello World!" example + \def\a#1.{#1} + \def\b#1:{#1.} + \def\c#1,{#1:} + \def\d{Hello world!,} + \edef\foo{\unexpanded\MultiExpandAfter{3}{% + \MultiExpandAfter{3}\a + \MultiExpandAfter{3}\b + \MultiExpandAfter{1}\c + \d}} + \def\fooB{Hello world!} + \ifx\foo\fooB\message{Correct! }\else\show\WRONG\fi + % now uses 32 \expandafters, slightly better than Hendrik's solution (however, we should count the overhead with all the \csname and friends). The other example on which Hendrik was optimizing, namely, expanding seven tokens once each in the reverse order, takes 74 \expandafter: + \def\a{a} \def\b{b} \def\c{c} \def\d{d} + \def\e{e} \def\f{f} \def\g{g} + \begingroup\tracingall\tracingonline=0\relax + \xdef\foo{\unexpanded\MultiExpandAfter{2}{% + \MultiExpandAfter3\a \MultiExpandAfter3\b + \MultiExpandAfter3\c \MultiExpandAfter3\d + \MultiExpandAfter3\e \MultiExpandAfter1\f\g}} + \endgroup + % Some experimentation tells me that the number of \expandafter is roughly 5 times the sum of the arguments of the various \MultiExpandAfter. + \csname bye\endcsname + \csname stop\endcsname +% +%<*internal> +\fi +\def\nameofplainTeX{plain} +\ifx\fmtname\nameofplainTeX\else + \expandafter\begingroup +\fi +% +%<*install> +\input docstrip.tex +\keepsilent +\askforoverwritefalse +\preamble +---------------------------------------------------------------- +multiexpand --- trigger multiple expansions in one expansion step. +E-mail: blflatex@gmail.com +Released under the LaTeX Project Public License v1.3c or later +See http://www.latex-project.org/lppl.txt +---------------------------------------------------------------- + +\endpreamble +\postamble + +Copyright (C) 2011-2013 by Bruno Le Floch + +This work may be distributed and/or modified under the +conditions of the LaTeX Project Public License (LPPL), either +version 1.3c of this license or (at your option) any later +version. The latest version of this license is in the file: + +http://www.latex-project.org/lppl.txt + +This work is "maintained" (as per LPPL maintenance status) by +Bruno Le Floch. + +This work consists of the file multiexpand.dtx +and the derived files multiexpand.ins, + multiexpand.pdf and + multiexpand.sty. + +\endpostamble +\usedir{tex/latex/multiexpand} +\generate{ + \file{\jobname.sty}{\from{\jobname.dtx}{package}} +} +% +%\endbatchfile +%<*internal> +\usedir{source/latex/multiexpand} +\generate{ + \file{\jobname.ins}{\from{\jobname.dtx}{install}} +} +\usedir{source/latex/multiexpand} +\generate{ + \file{\jobname-example.tex}{\from{\jobname.dtx}{example}} +} +\nopreamble\nopostamble +\usedir{doc/latex/multiexpand} +\generate{ + \file{README.md}{\from{\jobname.dtx}{readme}} +} + +\ifx\fmtname\nameofplainTeX + \expandafter\endbatchfile +\else + \expandafter\endgroup +\fi +% +%<*driver> +\documentclass[12pt]{ltxdoc} +\usepackage[T1]{fontenc} +\usepackage{multiexpand} +\usepackage[margin=4cm]{geometry} +\usepackage{hyperref} +\RecordChanges +\begin{document} + \DocInput{multiexpand.dtx} +\end{document} +% +% \fi +% +% \CheckSum{60} +% +% \def\fileversion{1.1} \def\filedate{2013/01/08} +%\title{\texttt{multiexpand}\\ +% Trigger multiple expansions \\ in one expansion step\thanks{This file +% describes version \fileversion, last revised \filedate.}} +%\author{Bruno Le Floch\thanks{E-mail: blflatex@gmail.com} +% \thanks{I have gathered ideas from various posts in the \texttt{\{TeX\}} +% community at \url{http://tex.stackexchange.com}. Thanks to their authors.}} +%\date{Released \filedate} +% +%\maketitle +% +% \tableofcontents +% \changes{v1.0}{2011/02/15}{First version with documentation} +% \changes{v1.1}{2013/01/08}{Version submitted to CTAN} +% +% \section{Two user commands} +% +% \begin{itemize} +% \item For $n>0$, expanding |\MultiExpand{|$n$|}\macro| twice gives +% the $n$-th expansion of |\macro|. +% \item For $n>0$, expanding |\MultiExpandAfter{|$n$|}\macroA\macroB| +% twice expands |\macroB| $n$ times before expanding |\macroA|. +% \end{itemize} +% Note that neither functions work for $n = 0$. +% +% These can typically be combined as +% \begin{verbatim} +% \MultiExpand{7}% +% \MultiExpandAfter{4}\a\MultiExpandAfter{7}\b% +% \MultiExpandAfter{3}\c\d +% \end{verbatim} +% which would expand |\d| $3$~times, then |\c| $5$~times ($2$~of the $7$~times +% were used to expand |\MultiExpandAfter{3}|), then |\b| twice ($4-2$), and +% finally |\a| five times ($7-2$). Note that all this happens in precisely +% \emph{two} steps of expansion. +% +% In some cases, one needs to achieve the same effect in \emph{one} step +% only. For this, we use the first expansion of |\MultiExpand|, which +% is |\romannumeral| |\multiexpand|, or of |\MultiExpandAfter|, which is +% |\romannumeral| |\multiexpandafter|). Expanding |\romannumeral| +% |\multiexpand{|$n$|}| once expands the following token $n$ times, and +% similarly for |\romannumeral| |\multiexpandafter{|$n$|}|. +% +% These are especially useful when we want to expand several times a +% very specific token which is buried behind many others. Example: +% expanding the following code twice, +% \begin{verbatim} +% \MultiExpand{3}\expandafter\macroA\expandafter\macroB% +% \romannumeral\multiexpandafter{4}\macroC\macroD +% \end{verbatim} +% will expand |\macroD| $4$ times, then will expand |\macroA| $2=3-1$ +% additional times. +% +% Note: as we mentionned, this breaks for $n=0$. But in this case, consider +% using |\expandafter\empty|, or a variant thereof. +% +% \section{How it works} +% +% The primitive |\romannumeral| expands what follows fully until it builds +% a full number. It will remove exactly one trailing space if the first +% non-digit token is a space. So if we expand the construction +% |\romannumeral0\expandafter\space| once, then |\romannumeral| will see +% the |0|, and expand |\expandafter|: it cannot yet be sure that it won't +% find another digit afterwards. This expands the next token once. In other +% words, |\romannumeral0\expandafter\space| behaves as if it was not there. +% +% This is how we end our loop. Namely, |\multiexpand|\marg{$n$} checks +% if $n<2$, in which case it stops with |0\expandafter\space|. If $n\geq 2$, +% then it simply expands to |\multiexpand|\marg{$n-1$}, plus the relevant +% |\expandafter|s meant to expand the next token once.\footnote{Note +% to self: Possible optimization: put three \cs{expandafter} rather than +% one at the end, to to two expansions at once.} +% +% \section{Implementation} +%\StopEventually{\PrintChanges\PrintIndex} +% \begin{macrocode} +%<*package> +% \end{macrocode} +% +% We work inside a group, to change the catcode of |@|. So we will only +% do |\gdef|s. We also define a macro |\ME@use|. +% \begin{macrocode} +\begingroup +\catcode`\@=11\relax% +\gdef\ME@use#1{#1}% +% \end{macrocode} +% +% |\MultiExpand| and |\MultiExpandAfter| are simply shorthands to avoid +% typing |\romannumeral|. Drawback: they require two steps of expansion +% rather than only one. +% \begin{macrocode} +\gdef\MultiExpand{\romannumeral\multiexpand}% +\gdef\MultiExpandAfter{\romannumeral\multiexpandafter}% +% \end{macrocode} +% +% The |\romannumeral| is stopped by |0\space|. We insert the relevant +% |\expandafter| to do the work. +% \begin{macrocode} +\xdef\ME@endroman#1{0\noexpand\expandafter\space}% +\xdef\ME@endroman@after#1{0\noexpand\expandafter\space\noexpand\expandafter}% +% \end{macrocode} +% +% \begin{macrocode} +\long\gdef\multiexpand#1{% + \ifnum#1<2 \expandafter \ME@endroman% + \else \expandafter \ME@use% + \fi% + {\expandafter \multiexpand \expandafter {% + \number\numexpr#1-1\expandafter}}% +}% +% \end{macrocode} +% Almost identical definitions for expanding after... +% \begin{macrocode} +\long\gdef\multiexpandafter#1{% + \ifnum#1<2 \expandafter\ME@endroman@after% + \else \expandafter \ME@use% + \fi% + {\expandafter \multiexpandafter \expandafter {% + \number\numexpr#1-1\expandafter}\expandafter}% +}% +% \end{macrocode} +% Close the group. +% \begin{macrocode} +\endgroup +% \end{macrocode} +% +% \begin{macrocode} +% +% \end{macrocode} +%\Finale +\endinput + + + diff --git a/Master/texmf-dist/source/latex/multiexpand/multiexpand.ins b/Master/texmf-dist/source/latex/multiexpand/multiexpand.ins new file mode 100644 index 00000000000..a6d2341e1ee --- /dev/null +++ b/Master/texmf-dist/source/latex/multiexpand/multiexpand.ins @@ -0,0 +1,71 @@ +%% +%% This is file `multiexpand.ins', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% multiexpand.dtx (with options: `install') +%% ---------------------------------------------------------------- +%% multiexpand --- trigger multiple expansions in one expansion step. +%% E-mail: blflatex@gmail.com +%% Released under the LaTeX Project Public License v1.3c or later +%% See http://www.latex-project.org/lppl.txt +%% ---------------------------------------------------------------- +%% +\input docstrip.tex +\keepsilent +\askforoverwritefalse +\preamble +---------------------------------------------------------------- +multiexpand --- trigger multiple expansions in one expansion step. +E-mail: blflatex@gmail.com +Released under the LaTeX Project Public License v1.3c or later +See http://www.latex-project.org/lppl.txt +---------------------------------------------------------------- + +\endpreamble +\postamble + +Copyright (C) 2011-2013 by Bruno Le Floch + +This work may be distributed and/or modified under the +conditions of the LaTeX Project Public License (LPPL), either +version 1.3c of this license or (at your option) any later +version. The latest version of this license is in the file: + +http://www.latex-project.org/lppl.txt + +This work is "maintained" (as per LPPL maintenance status) by +Bruno Le Floch. + +This work consists of the file multiexpand.dtx +and the derived files multiexpand.ins, + multiexpand.pdf and + multiexpand.sty. + +\endpostamble +\usedir{tex/latex/multiexpand} +\generate{ + \file{\jobname.sty}{\from{\jobname.dtx}{package}} +} +\endbatchfile +%% +%% Copyright (C) 2011-2013 by Bruno Le Floch +%% +%% This work may be distributed and/or modified under the +%% conditions of the LaTeX Project Public License (LPPL), either +%% version 1.3c of this license or (at your option) any later +%% version. The latest version of this license is in the file: +%% +%% http://www.latex-project.org/lppl.txt +%% +%% This work is "maintained" (as per LPPL maintenance status) by +%% Bruno Le Floch. +%% +%% This work consists of the file multiexpand.dtx +%% and the derived files multiexpand.ins, +%% multiexpand.pdf and +%% multiexpand.sty. +%% +%% +%% End of file `multiexpand.ins'. diff --git a/Master/texmf-dist/tex/latex/multiexpand/multiexpand.sty b/Master/texmf-dist/tex/latex/multiexpand/multiexpand.sty new file mode 100644 index 00000000000..e69945c3c9f --- /dev/null +++ b/Master/texmf-dist/tex/latex/multiexpand/multiexpand.sty @@ -0,0 +1,56 @@ +%% +%% This is file `multiexpand.sty', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% multiexpand.dtx (with options: `package') +%% ---------------------------------------------------------------- +%% multiexpand --- trigger multiple expansions in one expansion step. +%% E-mail: blflatex@gmail.com +%% Released under the LaTeX Project Public License v1.3c or later +%% See http://www.latex-project.org/lppl.txt +%% ---------------------------------------------------------------- +%% +\begingroup +\catcode`\@=11\relax% +\gdef\ME@use#1{#1}% +\gdef\MultiExpand{\romannumeral\multiexpand}% +\gdef\MultiExpandAfter{\romannumeral\multiexpandafter}% +\xdef\ME@endroman#1{0\noexpand\expandafter\space}% +\xdef\ME@endroman@after#1{0\noexpand\expandafter\space\noexpand\expandafter}% +\long\gdef\multiexpand#1{% + \ifnum#1<2 \expandafter \ME@endroman% + \else \expandafter \ME@use% + \fi% + {\expandafter \multiexpand \expandafter {% + \number\numexpr#1-1\expandafter}}% +}% +\long\gdef\multiexpandafter#1{% + \ifnum#1<2 \expandafter\ME@endroman@after% + \else \expandafter \ME@use% + \fi% + {\expandafter \multiexpandafter \expandafter {% + \number\numexpr#1-1\expandafter}\expandafter}% +}% +\endgroup +%% +%% Copyright (C) 2011-2013 by Bruno Le Floch +%% +%% This work may be distributed and/or modified under the +%% conditions of the LaTeX Project Public License (LPPL), either +%% version 1.3c of this license or (at your option) any later +%% version. The latest version of this license is in the file: +%% +%% http://www.latex-project.org/lppl.txt +%% +%% This work is "maintained" (as per LPPL maintenance status) by +%% Bruno Le Floch. +%% +%% This work consists of the file multiexpand.dtx +%% and the derived files multiexpand.ins, +%% multiexpand.pdf and +%% multiexpand.sty. +%% +%% +%% End of file `multiexpand.sty'. diff --git a/Master/tlpkg/bin/tlpkg-ctan-check b/Master/tlpkg/bin/tlpkg-ctan-check index 395be88515c..2b7c6aedf97 100755 --- a/Master/tlpkg/bin/tlpkg-ctan-check +++ b/Master/tlpkg/bin/tlpkg-ctan-check @@ -287,7 +287,7 @@ my @TLP_working = qw( moreenum morefloats morehype moresize moreverb morewrites movie15 mp3d mparhack mpattern mpcolornames mpgraphics mpman-ru ms msc msg mslapa msu-thesis mtgreek - multenum multibbl multibib multicap multienv multirow + multenum multibbl multibib multicap multienv multiexpand multirow multido multiobjective munich musixguit musixtex musixtex-fonts musuos muthesis mversion mwcls mwe mxedruli diff --git a/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc b/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc index 3c942e7d102..aac575d4c76 100644 --- a/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc +++ b/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc @@ -503,6 +503,7 @@ depend multenum depend multibbl depend multicap depend multienv +depend multiexpand depend multirow depend mversion depend mwe diff --git a/Master/tlpkg/tlpsrc/multiexpand.tlpsrc b/Master/tlpkg/tlpsrc/multiexpand.tlpsrc new file mode 100644 index 00000000000..e69de29bb2d -- cgit v1.2.3