summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/doc/generic/texapi
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2010-06-18 15:55:40 +0000
committerKarl Berry <karl@freefriends.org>2010-06-18 15:55:40 +0000
commit6a610c4ffff82f7e5188bd0154b7859244e02447 (patch)
tree39e69457f4d5831b124063e76e5ad654679ae4ee /Master/texmf-dist/doc/generic/texapi
parent79527eba1a0ef70a5b911ebacf7fdc03a24615e9 (diff)
new generic package texapi (17jun10)
git-svn-id: svn://tug.org/texlive/trunk@19035 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/doc/generic/texapi')
-rw-r--r--Master/texmf-dist/doc/generic/texapi/README23
-rw-r--r--Master/texmf-dist/doc/generic/texapi/texapi-doc.pdfbin0 -> 188234 bytes
-rw-r--r--Master/texmf-dist/doc/generic/texapi/texapi-doc.tex1865
3 files changed, 1888 insertions, 0 deletions
diff --git a/Master/texmf-dist/doc/generic/texapi/README b/Master/texmf-dist/doc/generic/texapi/README
new file mode 100644
index 00000000000..83581ee38ba
--- /dev/null
+++ b/Master/texmf-dist/doc/generic/texapi/README
@@ -0,0 +1,23 @@
+This is the README file for the texapi package.
+Author: Paul Isambert.
+E-mail: zappathustra AT free DOT fr
+Comments and suggestions are welcome.
+Date: June 2010.
+
+The package is set of macros to write
+format-independent (and -aware) packages.
+It is, of course, format-independent,
+and requires e-TeX.
+Relevant information can be found in texapi-doc.pdf
+
+Files in this distributions:
+
+texapi.tex => The package (no wrapper files for format, of course).
+texapi-doc.tex => The source of the documentation.
+texapi-doc.pdf => The typeset documentation.
+
+To process the documentation source, you need the
+piTeX files (available on CTAN) on top of plain TeX
+with LuaTeX at least v.0.6. Non-free fonts are used.
+
+Licensing of this package is covered by LPPL. \ No newline at end of file
diff --git a/Master/texmf-dist/doc/generic/texapi/texapi-doc.pdf b/Master/texmf-dist/doc/generic/texapi/texapi-doc.pdf
new file mode 100644
index 00000000000..f0ca5546c18
--- /dev/null
+++ b/Master/texmf-dist/doc/generic/texapi/texapi-doc.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/generic/texapi/texapi-doc.tex b/Master/texmf-dist/doc/generic/texapi/texapi-doc.tex
new file mode 100644
index 00000000000..b50b850f928
--- /dev/null
+++ b/Master/texmf-dist/doc/generic/texapi/texapi-doc.tex
@@ -0,0 +1,1865 @@
+\input pitex % which \input's texapi (and YaX)
+
+\directlua{
+ fonts.expansions.setups['threepercent'].shrink = 4
+ fonts.expansions.setups['threepercent'].stretch = 4
+ }
+
+\setparameter document:
+ author = "Paul Isambert"
+ title = \texapi
+ pdftitle = TeXapi
+ version = 1.0 % hopefully...
+ date = "\the\month/\the\day/\the\year"
+ subject = "The TeXapi documentation."
+ display = outlines
+
+\setparameter page:
+ pagewidth = 32cm
+ pageheight = 30cm
+ lines = 45
+ hsize = 10cm
+ baselineskip = 14pt
+ left = 10cm
+ top = 5cm
+ parindent = 2em
+
+\setparameter font:
+ command = \titlefont
+ name = ChaparralPro-
+ size = 20pt
+ roman = Regular
+
+\setparameter font:
+ command = \tmainfont
+ name = ChaparralPro-
+ size = 12pt
+ roman = Regular
+ bold = Bold
+ italic = Italic
+
+\setparameter font:
+ command = \csmainfont
+ name = ChaparralPro-
+ size = 11pt
+ roman = Italic
+ bold = Bold
+ italic = Regular
+
+\def\mainfont{%
+ \ifcslist \csmainfont
+ \else \tmainfont \fi}
+
+\setparameter font:
+ command = \tcodefont
+ name = ltype
+ size = 9.5pt
+ type = ttf
+ roman = {}
+ bold = b
+ italic = o
+
+\setparameter font:
+ command = \cscodefont
+ name = ltype
+ size = 8.5pt
+ type = ttf
+ roman = {}
+ bold = b
+ italic = o
+
+\def\codefont{%
+ \ifcslist \cscodefont
+ \else \tcodefont\fi}
+\def\tcode#1{{\codefont#1}}%
+
+%
+%
+% OUTPUT
+%
+\newbox\codebox
+\newdimen\sepdim
+\sepdim=1.2pc
+
+\output={%
+ \setbox255=\vtop{\unvbox255}
+ \setbox\codebox=\vtop{\unvbox\codebox}
+ \ht255=\baselineskip
+ \ht\codebox=\baselineskip
+ \unless\ifx\bookmarktitle\prevbookmarktitle
+ {\def\TeX{TeX}\pdfoutline goto num \count0 {\bookmarktitle}}
+ \fi
+ \global\let\prevbookmarktitle\bookmarktitle
+ \shipout\vbox{%
+ \vbox to 0pt{%
+ \vss
+ \kern-20pt\hbox{\kern-120pt \pdfdest num \count0 xyz}\kern20pt
+ \hbox to \hsize{%
+ \spaceskip .8em plus .6em minus .3em
+ \titlefont\sc\descriptiontitle}
+ \kern2\baselineskip}%
+ \hbox{%
+ \box255
+ \kern\sepdim
+ \pdfliteral{
+ q
+ .95 g
+ -3 200 300 -1000 re f
+ Q
+ }
+ \box\codebox
+ }%
+ }
+ \advancepageno
+ }
+
+%
+%
+% \cslist
+
+\def\red{\color{.9 0 0}}
+\def\rcom#1{\red{\com#1}}
+\newbox\cslistbox
+\newife\ifexpcs
+\newif\ifcslist
+\newbox\tempbox
+\newdimen\tempdimen
+\newdimen\cswidth
+\newcount\cslistcount
+\def\zilch{\zilch}
+\extraboxspace=1.5pt
+\def\macrobox{\colorbox{.92 .92 .92}}
+\def\definecs#1#2{
+ \quitvmode
+ \hbox to\cswidth{\iffexpcs\macrobox{\unless\ifx#1\zilch\rcom#1\fi}\hfill}%
+ \setcatcodes{/=13}%
+ \scantextokens{#2}%
+ \restorecatcodes
+ }
+\def\longdefinecs#1#2\end{\definecs#1{#2}}
+\def\getwidth#1#2\end{%
+ \bgroup
+ \setbox0=\hbox{\codefont\string#1}%
+ \ifdim\wd0>\cswidth
+ \global\cswidth=\wd0
+ \fi
+ \egroup
+ }
+\def\cslist#1{%
+ \vskip\baselineskip
+ \cslisttrue \cslistcount=0
+ \cswidth=0pt
+ \dofornoempty{#1,}##1,{%
+ \deftrim\temp{##1}%
+ \passexpanded{\iffprefix!}{\temp}
+ {\passexpanded{\removeprefixin!}{\temp}\temp}%
+ \expandafter\getwidth\temp\end
+ }{}%
+%
+ \tempdimen=0pt
+ \dofornoempty{#1,}##1,{%
+ \advance\cslistcount1
+ \deftrim\temp{##1}%
+ \passexpanded{\ifprefix!}{\temp}
+ {\expcstrue\passexpanded{\removeprefixin!}{\temp}\temp}
+ {\expcsfalse}%
+ \setbox\tempbox\hbox{\expandafter\longdefinecs\temp\end\kern\sepdim}%
+ \ifdim\wd\tempbox>\tempdimen
+ \tempdimen=\wd\tempbox
+ \fi
+ }{}%
+%
+ \setbox\cslistbox=\vtop{%
+ \dofornoempty{#1,}##1,{%
+ \deftrim\temp{##1}%
+ \passexpanded{\ifprefix!}{\temp}
+ {\expcstrue\passexpanded{\removeprefixin!}{\temp}\temp}
+ {\expcsfalse}%
+ \llap{\hbox to\tempdimen{\expandafter\longdefinecs\temp\end\hfil}}%
+ }{}%
+ }%
+ \dp\cslistbox=0pt
+ \noindent \box\cslistbox
+ \def\par{%
+ \endgraf
+ \let\par\endgraf
+ \ifnum\prevgraf<\cslistcount
+ \vskip\the\numexpr(\cslistcount-\prevgraf)\baselineskip
+ \fi}%
+ \cslistfalse \ignorespaces
+ }
+%
+\bgroup
+\setcatcodes{/=13}
+\gdef/#1/{\arg{#1}}
+\egroup
+
+\def\true{\arg{true}}
+\def\false{\arg{false}}
+\def\csarg{\arg{csname}}
+\def\comarg{\arg{command}}
+
+
+%
+% EXAMPLES
+%
+
+\def\processexample{%
+ \global\setbox\codebox=\vbox{%
+ \parindent0pt
+ \ifvoid\codebox
+ \quitvmode\vrule height \topskip depth 0pt width 0pt
+ \else
+ \dimen0=\dp\codebox
+ \box\codebox
+ \vskip\baselineskip
+ \color{1 1 1}{\hrule width \hsize height 1pt depth 1pt}%
+ \kern-2pt
+ \vskip\baselineskip
+ \prevdepth=\dimen0
+ \fi
+ \let\exampleskip\relax
+ \cslisttrue \codefont
+ \typesetexample
+ \vskip\baselineskip
+ \mainfont
+ \doexample
+ }%
+ }
+
+\newblock\description
+ {\getdescriptiontitle}
+ {\penalty-10000\relax}
+
+\def\getdescriptiontitle#1{%
+ \def\bookmarktitle{#1}%
+ \def\descriptiontitle{}%
+ \dofor{#1 }##1 {%
+ \dofor{##1}####1{%
+ \addright\descriptiontitle{\lowercase{####1}\hskip0pt plus 8pt minus 2pt}%
+ }{}%
+ \addright\descriptiontitle{\unskip\spacecs}%
+ }{}%
+ \addright\descriptiontitle{\unskip}%
+ }
+\def\texapi{%
+ {\codefont texapi}%
+ \antigobblespace
+ }
+
+
+\mainfont
+
+
+
+\description{Writing macros with texapi}
+
+\setbox\codebox=\vbox to \hsize{%
+ \csmainfont
+ \hfill \vrule height\topskip width0pt Author: \usevalue document : author \par
+ \hfill Version: \usevalue document : version \par
+ \hfill Date: \usevalue document : date \par
+ \vskip\baselineskip
+ \noindent Typeset in Chaparral Pro (Carol Twombly)
+ and Lucida Sans Typewriter (Charles Bigelow and Kris Holmes)
+ with Lua\TeX\ v.\the\luatexversion.\luatexrevision.
+
+ }
+
+The first motivation for this set of macros is selfish:
+after rewriting the same lines over and over and wasting
+so many excruciating (yes!) hours debugging intricate loops
+with one typo, I decided I could use a toolkit containing
+the painful code without errors (hopefully) and use it
+for future packages.
+
+The second motivation is more ambitious: I think it's a pity
+so many packages are written for one format and are thus
+unusable outside it, even though those packages could be useful
+to anybody. This is so, I believe, because a format mixes two
+different things: decisions about typesetting (mainly) and utility macros.
+The former are the essence of a format, whereas the latter are just
+shorthands you can use or not, replace, or ignore completely.
+But the fact is that users of a format tend to use the utility macros
+shipped with it, and thus writes macros that can't be reused elsewhere,
+even though nothing crucial hinges on what utility macros one uses.
+Thus, \texapi aims at providing a good deal of this kind of macros
+whitout relying on any particular format, so that one can write
+code without having to take into account how it will be used.
+Moreover, \texapi is also format-aware, meaning some commands
+are defined differently depending on the format being used,
+and one doesn't have to create as many macros as there are formats.
+
+There is at least one basic assumptions, namely that formats
+should contain plain \TeX's allocation macros. This the case for
+all formats I know.
+
+\vskip\baselineskip
+In what follows, commands have a \macrobox{grey background} when they
+are fully expandable, e.g. they can be used inside \com\csname...\com\endcsname,
+provided you don't use them with unexpandable arguments, of course.
+On the other hand, all unexpandable commands are protected.
+
+Arguments are denoted by \arg{text}, where `text' makes the intended use
+clearer and doesn't denote any particular type of argument, except in
+the case of \comarg, which denotes a control sequence (something expandable,
+actually), and \csarg, which denotes an argument suitable to \com\csname.
+Braces are indicated only when mandatory, but of course they can be used to delimit
+arguments as usual.
+
+\description/
+
+
+
+\description{Engine and format detection}
+
+\cslist{
+ \texenginenumber
+ }
+This is a \com\chardef'ined number set according to the
+engine used: 0 means e-\TeX, or an unknown engine with
+e-\TeX\ extensions; 1 means Xe\TeX\ (detected because
+\com\XeTeXinterchartoks exists); 2 means pdf\TeX\ (detected
+thanks to \com\pdfstrcmp); 3 means Lua\TeX\ (detected thanks
+to \com\directlua). Numbering here allows one to detect a
+pdf\TeX-based engine with \com\texenginenumber>1. Con\TeX t
+has an equivalent \com\texengine, with pdf\TeX=1 and Xe\TeX=2,
+though.
+
+\cslist{
+ \formatnumber
+ }
+This number does the same with formats. Here, 0 means an unknown
+format, 1 means plain (because \com\fmtname is `\tcode{plain}'),
+2 means eplain (because \com\fmtname is `\tcode{eplain}'),
+3 means Con\TeX t (because there exists an \com\inspectnextoptionalcharacter
+command), 4 means La\TeX2e (because \com\fmtname is `\tcode{LaTeX2e}')
+and 5 means La\TeX3 (because there exists an \com\ExplSyntaxOn command).
+There's no distinction yet between La\TeX3 on top of La\TeX2e and La\TeX3
+as a format per se. Since \com\formatnumber is set only if it doesn't
+already exist, you can write your package with, say, \tcode{code.tex}
+containing the main code and \tcode{code.sty} and \tcode{t-code.tex}
+as wrapper files for La\TeX\ and Con\TeX t respectively, with \com\formatnumber
+already set accordingly.
+
+\Example
+\def\myengine{%
+ \ifcase\texenginenumber
+ e-\or Xe\or pdf\or Lua\fi\TeX
+ }
+\def\myformat{%
+ \ifcase\formatnumber
+ unknown\or plain\or eplain\or
+ ConTeXt\or LaTeX\or LaTeX3\fi
+ }
+This documentation has been typeset
+with \myformat\ under \myengine.
+\Example/
+
+\cslist{
+ \priminput,
+ \primunexpanded
+ }
+Both La\TeX\ and Con\TeX t redefines \com\input, and in Con\TeX t
+\com\unexpanded has not the meaning of the e-\TeX\ primitive. These
+two commands are thus the primitive \com\input and \com\unexpanded
+respectively.
+
+\cslist{
+ \loadmacrofile/file/
+ }
+The behavior of this command depends on \com\formatnumber. The \arg{file}
+should be given without extension, and the following happens: in Con\TeX t,
+\com\usemodule\tcode{[\arg{file}]} is executed, in La\TeX\ \com\RequirePackage\barg{file}
+is used, and in other formats it is simply \com\input\arg{file}\tcode{.tex}.
+This makes sense only with packages that are distributed as described above,
+i.e. with the main code in one file and wrapper files for La\TeX\ and Con\TeX t,
+like Ti\ital{k}Z or \ital{librarian}.
+
+\cslist{
+ \senderror/package//message/
+ }
+This sends an error message according to the format's custom. In \tcode{plain}
+and \tcode{eplain} (and in an unknown format), it produces
+\tcode{\com\errmessage\string{\arg{package} error: \arg{message}\string}}.
+In La\TeX, we get \com\PackageError\barg{package}\barg{message}{\codefont\string{\string}}
+(no help message) and in Con\TeX t
+\tcode{\com\writestatus\string{\arg{package} error\string}}\barg{message}
+(which is far from Con\TeX t's sophisticated communication system but, well...).
+
+\description/
+
+
+
+
+
+
+
+\description{Argument manipulation}
+
+\cslist{
+ !\emptycs,
+ !\spacecs,
+ \spacechar
+ }
+Pretty useful macros whose meaning is clear, but whatever: \com\emptycs is
+an emptily defined command, \com\spacecs expands to a space, and \com\spacechar
+denotes a space, i.e. it is an implicit space and not really a macro.
+
+\cslist{
+ !\gobbleone,
+ !\gobbleoneand/code/
+ }
+Those, as you might imagine, gobble the following argument; the second version
+also excutes \arg{code} afterwards. There are actually nine
+such commands in each case, and they are (for the sake of completeness)
+\com\gobbleone, \com\gobbletwo, \com\gobblethree, \com\gobblefour,
+\com\gobblefive, \com\gobblesix, \com\gobbleseven, \com\gobbleeight\
+(watch out, two \ital{e}'s) and \com\gobblenine for the first version,
+and \com\gobbleoneand, \com\gobbletwoand, \com\gobblethreeand,
+\com\gobblefourand, \com\gobblefiveand, \com\gobblesixand,
+\com\gobblesevenand, \com\gobbleeightand and \com\gobblenineand. Note
+that \com\gobblenineand\arg{code} takes two expansion steps to
+return \arg{code}, instead of only one in the other cases.
+
+\Example
+This is \gobbletwoand{very } uninteresting.
+\Example/
+
+\cslist{
+ !\unbrace/code/
+ }
+This is the kind of command you probably can't see the point of until
+you need it. It returns its \arg{code} untouched, but with outermost
+braces removed if any.
+
+\cslist{
+ !\swapargs/arg1//arg2/,
+ !\swapbraced/arg1//arg2/,
+ !\swapleftbraced/arg1//arg2/,
+ !\swaprightbraced/arg1//arg2/
+ }
+The first of those returns \arg{arg2}\arg{arg1} into the stream, without
+any brace to delimit them.
+On the contrary, \com\swapbraced returns \barg{arg2}\barg{arg1}. And, as
+you might imagine, \com\swapleftbraced returns
+\barg{arg2}\arg{arg1} whereas \com\swaprightbraced returns \arg{arg2}\barg{arg1}.
+
+\cslist{
+ !\passexpanded/arg1//arg2/,
+ !\passexpandednobraces/arg1//arg2/
+ }
+The first one returns \arg{arg1}\barg{arg2 expanded once} and the second
+\arg{arg1}\arg{arg2 expanded once}. It's some sort
+of long \com\expandafter built on \com\swapargs and associates,
+and if \arg{arg1} is a single token it's faster to use \com\expandafter
+itself. It's not a real \com\expandafter, though, since \arg{arg2} is
+expanded to the left of \arg{arg1} and then moved back to its
+right. Which, with e.g. an \com\else as \arg{arg2}, will lead
+to results you probably haven't foreseen and expected.
+If \arg{arg2} is some material you want to turn into a command with
+\com\csname, see \com\passcs below.
+
+\Example
+\def\foo#1#2{\detokenize{(1=#1,2=#2)}}
+\def\bar{two}
+\foo{one}\bar
+\passexpanded{\foo{one}}\bar
+\Example/
+
+\description/
+
+
+
+
+
+
+
+
+
+\description{Defining \& using commands}
+
+\cslist{
+ \defcs\csarg/parameter text/\barg{definition},
+ \edefcs\csarg/parameter text/\barg{definition},
+ \gdefcs\csarg/parameter text/\barg{definition},
+ \xdefcs\csarg/parameter text/\barg{definition}
+ }
+These work exactly like \com\def, \com\edef, \com\gdef
+and \com\xdef, except they define a command with name
+\csarg. The \arg{parameter text} is the usual one,
+and any the space at the beginning is significant. I.e.
+\verb/\defcs{foo}#1{...}/ and \verb/\defcs{foo} #1{...}/
+aren't equivalent at all. Prefixes can be appended as with
+\com\def.
+
+\Example
+\defcs{foo}#1{This is foo: #1.}
+\foo{bar}
+\Example/
+
+
+\cslist{
+ \letcs\csarg\comarg,
+ \lettocs\comarg\csarg,
+ \letcstocs\csarg\csarg
+ }
+These \com\let the first command or command named \csarg\ to
+the meaning of the second one. In both \com\lettocs and \com\letcstocs,
+if the command with name \csarg\ is undefined, it is not let to \com\relax.
+So these are different from \com\let with \com\expandafter's. The \com\letcs
+command can also be used to create an implicit character, of course.
+
+\Example
+\expandafter\let\expandafter\foo
+ \csname undefined\endcsname
+\lettocs\bar{reallyundefined}
+\letcstocs{reallyundefined}{reallyundefined}
+
+Compare this: \meaning\foo,
+and that: \meaning\bar.
+And better yet: \meaning\reallyundefined.
+\Example/
+
+
+\cslist{
+ \addleft\comarg/material/,
+ \addleftcs\csarg/material/,
+ \eaddleft\comarg/material/,
+ \eaddleftcs\csarg/material/
+ }
+This redefines \comarg\ or a command named \csarg\ to
+itself with \arg{material} added at the beginning. The e-variant
+performs an \com\edef so that \arg{material} is fully expanded
+(but not \comarg). The usual prefixes can be appended.
+
+\cslist{
+ \addright\comarg/material/,
+ \addrightcs\csarg/material/,
+ \eaddright\comarg/material/,
+ \eaddrightcs\csarg/material/
+ }
+This is the same thing as above, but the material is added
+at the end. In both the left and right version, the command
+thus redefined should be a simple command working by itself
+(i.e. no argument and no delimiter). In the \csarg\ case,
+no check is performed to ensure that \csarg\ is defined
+(but in the worst case it ends up as \com\relax, because of
+its being called after the implicit \com\def\ (get it?)).
+
+\Example
+\defcs{foo}{bar}
+\addleftcs{foo}{In a }
+\addright\foo{ (how fascinating).}
+\foo
+\Example/
+
+\cslist{
+ !\usecs\csarg,
+ !\usecsafter\csarg,
+ !\passcs/code/\csarg,
+ !\passexpandedcs/code/\csarg,
+ \noexpandcs\csarg,
+ \unexpandedcs\csarg
+ }
+Various ways to use a command with name \csarg:
+\com\usecs performs a simple \com\csname\csarg\com\endcsname\
+(and doesn't even check whether \csarg\ is defined or not, so
+this might relax it a little bit), \com\usecsafter does the equivalent
+of \com\expandafter\com\command, \com\passcs puts \csarg\ as a real
+(unbraced) command after \arg{code}, whereas \com\passexpandedcs passes
+the expansion of the control sequence with name \csarg\ to \arg{code}; \com\noexpandcs and \com\unexpandedcs
+return \csarg\ with a \com\noexpand prefix or its expansion as argument to
+\com\unexpanded\ (\com\primunexpanded, really).
+
+\Example
+\def\bar{whatever} \def\foo#1{[#1]}
+I use it: \usecs{bar},
+I use it after: \usecsafter{foo}\bar,
+and I pass it: \passcs\foo{bar}.
+\Example/
+\Example
+\def\foo{\bar}
+I don't expand it:
+\edef\foobar{\noexpandcs{foo}}%
+\meaning\foobar.
+Or just a little bit:
+\edef\foobar{\unexpandedcs{foo}}%
+\meaning\foobar.
+\Example/
+
+\cslist{
+ !\commandtoname\comarg
+ }
+This returns the name of \comarg, i.e. \comarg\ without its backslash
+(and made of catcode-12 characters, since it's based on \com\string).
+
+\description/
+
+
+
+
+
+
+
+
+
+\description{Tests with commands}
+
+\cslist{
+ !\reverse
+ }
+Conditionals in \texapi\ (not only those on this page) can
+be prefixed with \com\reverse, so that if they're true the
+\false\ argument is executed (if specified), and if they're
+false, the \true\ argument is executed. So this is equivalent
+to \com\unless.
+
+\cslist{
+ !\ifcommand\comarg\true\false,
+ !\iffcommand\comarg\true
+ }
+This conditional executes \true\ if \comarg\ is defined.
+So it is a straight version of \com\ifdefined. The \com\iff...
+version, like all \texapi's \com\iff..., considers only the
+\true\ case (which becomes the \false\ case if the conditional
+is prefixed with \com\reverse).
+
+\Example
+\ifcommand\TeX{Cool}{Too bad}.
+Nothing: \iffcommand\undefined{Whatever}.
+\Example/
+
+\cslist{
+ !\ifcs\csarg\true\false,
+ !\iffcs\csarg\true
+ }
+Same as above, but with an \com\ifcsname this time.
+It goes without saying that \csarg\ isn't let to \com\relax
+thereafter if it was undefined.
+
+\Example
+\reverse\iffcs{undefined}{This command is undefined.}
+\Example/
+
+\cslist{
+ !\ifemptycommand\comarg\true\false,
+ !\iffemptycommand\comarg\true
+ }
+This is true if \comarg\ is defined with an empty
+definition text, i.e. it is equivalent to \com\emptycs.
+This is not true if \comarg\ takes arguments, though,
+so \com\gobbleone isn't empty in this sense.
+
+\cslist{
+ !\ifemptycs\csarg\true\false,
+ !\iffemptycs\csarg\true
+ }
+Same as above with a command named \csarg.
+
+\Example
+\def\foo{}
+\ifemptycommand\foo{Empty}{Not empty}.
+\reverse\iffemptycs{gobbleone}{It ain't empty}.
+\Example/
+
+
+
+\cslist{
+ !\ifxcs\csarg\comarg\true\false,
+ !\iffxcs\csarg\comarg\true
+ }
+This is true if \csarg\ has the same definition as \comarg,
+or they're both undefined.
+
+\cslist{
+ !\ifxcscs\csarg\csarg\true\false,
+ !\iffxcscs\csarg\csarg\true
+ }
+This is true if both \csarg's have the same definition,
+or they're both undefined.
+
+\Example
+\iffxcs{undefined}\undefinedtoo
+ {Same definitions.}
+\ifxcscs{foo}{TeX}
+ {These are the same}
+ {These are different}.
+\Example/
+
+\description/
+
+
+
+
+
+
+
+
+
+
+\description{Various conditionals}
+
+\cslist{
+ \newife\comarg
+ }
+This defines a conditional like plain \TeX's \verb/\newif/,
+except it takes two arguments (the \true\ and \false\ values)
+instead of an \com\else ... \com\fi structure. Besides,
+this conditional is reversible with \com\reverse, and
+a `double-f\kern1pt' (i.e. \com\iff...) version is also created,
+which takes the \true\ part only. As with
+\verb/\newif/, \comarg\ must begin with \tcode{if}.
+(The \ital{e} means \ital{expandable}, although there's
+nothing more expandable in the conditionals thus constructed
+than in those defined with \verb/\newif/, but anyway.)
+
+\Example
+\newife\iffoo
+\iffoo{There is foo}{There is no foo}.
+\footrue
+\reverse\iffoo{There is no foo}{There is foo}.
+\ifffoo{With three f's in a row}.
+\Example/
+
+\cslist{
+ !\straightenif/\TeX\ conditional//arg/\true\false,
+ !\straighteniff/\TeX\ conditional//arg/\true
+ }
+Apart from \com\ifdefined and \com\ifcsname\ (in the guise
+of \com\ifcommand and \com\ifcs respectively), none of \TeX's
+primitive conditionals are redefined in a straight fashion,
+i.e. with two arguments instead of \com\else ... \com\fi.
+These commands let you use \TeX's conditional in such a way.
+\arg{\TeX\ conditional} means such a primitive without a
+backslash (so this construction can be used inside real
+conditionals), e.g. \tcode{ifnum} or \tcode{ifvoid}.
+The \arg{arg} is whatever you normally feed to this conditional.
+It is brutally concatenated, and you're the one in charge
+of adding space if needed, as for instance with \tcode{ifnum}.
+Chaos will ensue if you fail to do so. With conditionals that don't
+require anything, e.g. \tcode{iftrue} or \tcode{ifvmode},
+leave \arg{arg} empty (but don't forget it).
+Finally, \true\ and \false\ are executed accordingly, and the
+whole macro can be prefixed with \com\reverse.
+
+\Example
+ % See this space?
+\straightenif{ifnum}{1=1 }{Reality is preserved}
+ {Bad news}.
+\reverse\straighteniff{if}{ab}
+ {Different letters, obviously.}
+\straightenif{iftrue}{}{Good}{Bad}.
+\Example/
+
+
+
+
+\cslist{
+ !\afterfi/code/,
+ !\afterdummyfi/code/
+ }
+You shouldn't use these. The first one closes the
+current conditional and executes \arg{code}. The second
+one lets go one \com\fi and executes \arg{code}. So these
+are kinds of \com\expandafter's when \arg{code} isn't just
+a command. Anything before the incoming \com\fi is gobbled.
+The reason why you should use one or the other
+should be clear to you, otherwise you'll probably be messing
+with a conditional.
+
+\Example
+\iftrue
+ \afterdummyfi{\afterfi{Here we are.}}
+\else
+ \iffalse
+ Whatever.
+ \fi
+\fi
+\Example/
+
+\description/
+
+
+
+
+
+
+
+
+\description{Poking at what comes next}
+
+\cslist{
+ \nospace/code/
+ }
+This gobbles any incoming space, if any, and executes \arg{code}.
+Of course it doesn't require there to be any space to work properly.
+
+\vskip\baselineskip
+
+All the following conditionals can be prefixed with \com\reverse.
+And in case your head's buzzing, their names are quite regular:
+take an \com\if, \com\ifcat or \com\ifx, add `\tcode{next}', and create
+variants by doubling the \tcode{f} and/or adding \tcode{nospace}
+at the end.
+
+\Example
+\nospace{foo} bar
+\Example/
+
+\cslist{
+ \ifnext/token/\true\false,
+ \iffnext/token/\true,
+ \ifnextnospace/token/\true\false,
+ \iffnextnospace/token/\true
+ }
+These poke at the next token and see whether it
+has the same character code as \arg{token}. In other
+words, an \com\if test is performed between \arg{token}
+and the next token in the input stream. However, neither
+\arg{token} nor the incoming token are expanded, so that
+they can be control sequences and no unwanted expansion
+will occur. Control sequences are all equal according to
+this test (which can very well take an undefined control
+sequence as \arg{token}). The nospace version must be
+pretty clear: the macro discards all incoming spaces until
+it finds a non-space token to test (unfortunately,
+an implicit space and a space character are undistinguishable
+as far as this test (and the next ones) is concerned, so in
+the very unlikely case where an implicit space was waiting
+in the stream, it'll be gobbled in the nospace variant).
+
+\Example
+Here comes \ifnext e{an }{a }e.
+Here comes \reverse\ifnext e{a }{an }b.
+Here comes
+\iffnextnospace\foo{a control sequence: } \TeX.
+\Example/
+
+\cslist{
+ \ifcatnext/token/\true\false,
+ \iffcatnext/token/\true,
+ \ifcatnextnospace/token/\true\false,
+ \iffcatnextnospace/token/\true
+ }
+These are the same as above with an \com\ifcat test
+instead of \com\if. Again, control sequences aren't expanded
+and they all have the same category code.
+
+\Example
+\def\tex{\TeX\iffcatnext a{ }}
+A \tex is a \tex is a \tex.
+\Example/
+
+\cslist{
+ \ifxnext/token/\true\false,
+ \iffxnext/token/\true,
+ \ifxnextnospace/token/\true\false,
+ \iffxnextnospace/token/\true
+ }
+Once again like the previous commands, this time with
+an \com\ifx, i.e. the definitions of control sequences
+are compared, and in case \arg{token} and/or the next
+token are unexpandable thing, both character code and
+category code are compared. So these are performing
+real \com\ifx tests.
+
+\Example
+\def\foo{not \string\TeX}
+\reverse\iffxnextnospace\TeX
+ {The incoming command isn't \string\TeX: } \foo.
+\Example/
+
+\description/
+
+
+
+
+
+
+\description{String manipulation}
+
+\cslist{
+ !\ifstring/string1//string2/\true\false,
+ !\iffstring/string1//string2/\true
+ }
+These return \true\ if the two strings are identical.
+Category codes aren't taken into account when strings
+are compared.
+
+\Example
+Two \ifstring{abc}{abc}{equal}{unequal} strings
+and an \reverse\iffemptystring{something}{unempty} one.
+\Example/
+
+
+\cslist{
+ !\ifemptystring/string/\true\false,
+ !\iffemptystring/string/\true
+ }
+These return \true\ if \arg{string} is empty.
+
+
+
+
+\cslist{
+ \newstring/string/
+ }
+The following operations (\com\ifprefix, \com\removesuffix, etc.)
+aren't fully expandable by default. However, if a string has been
+previously declared with \com\newstring, they magically become
+fully expandable.
+
+So, in what follows, macros aren't marked as expandable, although
+they can be if the preceding condition is fulfilled. Besides, these
+macro aren't \com\protected even though their default behavior would
+require that they be. But you can always append a \com\noexpand to
+an unprotected command, whereas you cannot force the execution of a
+protected one. (This protecting issue is of course totally irrelevant
+for the \com\removeprefixin and \com\removesuffixin commands, which aren't
+expandable by definition and are thus protected.)
+
+
+
+
+\cslist{
+ \ifprefix/prefix//string/\true\false,
+ \iffprefix/prefix//string/\true
+ }
+This test is true if \arg{string} begins with \arg{prefix}.
+Category codes do matter.
+
+\Example
+\newstring{abc}
+\edef\foo{\ifprefix{abc}{abcd}{True}{False}.}
+\edef\bar{\reverse\iffsuffix{abc}{whatever}{No suffix}.}
+\edef\foobar{\ifcontains{abc}{gee}{Yes}{No}.}
+\meaning\foo\par
+\meaning\bar\par
+\meaning\foobar
+\Example/
+
+\cslist{
+ \ifsuffix/suffix//string/\true\false,
+ \iffsuffix/suffix//string/\true
+ }
+True if \arg{string} ends with \arg{suffix}.
+
+\cslist{
+ \ifcontains/string1//string2/\true\false,
+ \iffcontains/string1//string2/\true
+ }
+Finally, this is true if \arg{string2} contains \arg{string1}.
+
+
+\cslist{
+ \removeprefix/prefix//string/,
+ \removesuffix/suffix//string/
+ }
+These return \arg{string} without \arg{prefix} (resp.
+\arg{suffix}). No test is performed to check that
+\arg{string} indeed begins (resp. ends) with \arg{prefix}
+(resp \arg{suffix}), so these macros make sense only after
+the adequate tests.
+
+\cslist{
+ \removeprefixand/prefix//string//code/,
+ \removesuffixand/suffix//string//code/
+ }
+These do the same as the previous one, but feed the
+resulting string to \arg{code}, between braces. Once again,
+no test is performed beforehand.
+
+\cslist{
+ \removeprefixin/prefix//string/\comarg,
+ \removesuffixin/suffix//string/\comarg
+ }
+These define \comarg\ as \arg{string} without \arg{prefix}
+(resp. \arg{suffix}). No test either. Sorry.
+
+\cslist{
+ \splitstring/string1//string2//code/
+ }
+This cuts \arg{string2} in two at \arg{string1}'s first occurrence
+and passes the two parts as braced arguments to \arg{code}. And,
+again: no test.
+
+\Example
+\def\record#1 : #2.{%
+ \par\bgroup
+ \it\ifprefix*{#1}{\removeprefix*{#1} [live]}{#1}
+ \egroup
+ (\ifcontains/{#2}{\splitstring/{#2}{\dodate}}{#2})
+ }
+\def\dodate#1#2{recorded #1, released #2}
+
+A somewhat incomplete list of fantastic
+records by Frank Zappa:
+\record Absolutely Free : 1967.
+\record The Grand Wazoo : 1972.
+\record L\"ather : 1977/1996.
+\record *Make a Jazz Noise Here : 1988/1991.
+\Example/
+
+\description/
+
+
+
+
+
+
+\description{Various things on the same page}
+
+\cslist{
+ \setcatcodes\barg{list}
+ }
+The \arg{list} argument here means comma separated
+\arg{characters}\verb/=/\arg{category code}, with
+an \ital{s} to \ital{characters} because you can
+concatenate them if you want them to share the same
+\arg{category code}. So, as you might have guessed,
+this set all \arg{characters} to characters with
+catcode \arg{category code}. And it also sets
+\com\restorecatcodes accordingly. The changes are
+local. The \verb/#/ character requires a backslash
+(so do braces and the backslash itself, but that's obvious).
+
+\cslist{
+ \resetcatcodes
+ }
+This restores the catcodes of the characters changed
+with the previous command, which is cumulative, i.e.
+\com\restorecatcodes restores catcodes changed by all preceding
+\com\setcatcodes commands, not only the last one. Since
+changes are local, \com\restorecatcodes may be useless in a group
+(and the effect of \com\restorecatcodes itself is local too).
+
+\Example
+\setcatcodes{\\\#\{\}\%=12,\|=0}
+Hey, were're verbatimizing:
+\def\foo#1{\bar{#1}}%
+|restorecatcodes
+\Example/
+
+\Example
+\bgroup
+And now in a group:\par
+\setcatcodes{z=13}
+\defz{ZZZZZZZZZZZZZZZZZZZZZZZZZZ}
+I'm sleeping: z.\par
+\egroup
+And I'm not: z.
+\Example/
+
+
+
+\vskip\baselineskip
+The trimming macros below are adapted from
+Will Robertson's \tcode{trimspace} package.
+
+
+\cslist{
+ !\trimleft/string/,
+ !\trimright/string/,
+ !\trim/string/
+ }
+These return \arg{string} with one space removed at the beginning
+or end or both. There's no need to check beforehand whether there
+are indeed such spaces.
+
+\Example
++\trim{ bar }+
+\Example/
+
+\cslist{
+ !\passtrimleft/string//code/,
+ !\passtrimright/string//code/,
+ !\passtrim/string//code/
+ }
+These return \arg{string} trimmed of spaces as a braced argument to
+\arg{code}.
+
+\cslist{
+ \deftrimleft\comarg/string/,
+ \deftrimright\comarg/string/,
+ \deftrim\comarg/string/
+ }
+The same thing again, except now those commands define \comarg\
+to \arg{string}, etc.
+
+\Example
+\deftrimleft\foo{ bar }
++\foo+
+\Example/
+
+\description/
+
+
+
+
+
+
+
+\description{While statements}
+
+\cslist{%
+ !\repeatuntil/number//code/
+ }
+This executes \arg{code} \arg{number} times. The \arg{number}
+argument can be a \com\count register, an integer defined with
+\com\chardef, etc., and of course a string of digits. In any case,
+it is really an argument and must be surrounded by braces if it is
+made of more than one token.
+
+\Example
+We have seen \repeatuntil\pageno{I} pages.\par
+\edef\foo{\repeatuntil3{.}}
+\meaning\foo
+\Example/
+
+
+\cslist{
+ !\dowhile/condition//code/
+ }
+This repeats \arg{code} while \arg{condition} is true. The latter
+must be a `straight' \tcode{if}, i.e. either one of \texapi's
+\com\if... or a \com\straightenif\barg{\TeX\ conditional} construction,
+in both cases without the \true\ and \false\ arguments, because \true\ is actually
+\arg{code}, and \false\ would make no sense. Finally, the conditional
+must be a simple \com\if..., not an \com\iff... version. Once again, this
+makes sense: the \ital{if and only if} clause is implicit in a \ital{while}
+statement. If you use an \com\iff..., you'll end up with many empty braces,
+which is harmless unless you're in a context of expansion. You can use \com\reverse
+in \arg{condition}.
+
+\Example
+\newife\ifbreakloop \def\foo{}
+\dowhile{\reverse\ifbreakloop}
+ {\addleft\foo{a}%
+ \passexpanded\iffstring\foo{aaaa}
+ \breaklooptrue}
+\foo
+\Example/
+
+\Example
+\edef\foo{%
+ The inconvenience of iff...:
+ \dowhile{\straighteniff{ifnum}{4=5 }}
+ {whatever}
+ }
+\meaning\foo
+\Example/
+
+
+
+\cslist{
+ \newwhile\comarg/number//transformations//code/
+ }
+The \com\dowhile macro is not very powerful since
+you must generally change something somewhere to make
+it stops, and thus its expandability is somewhat perfunctory.
+That's why there is \com\newwhile. It creates an expandable \comarg\ which takes
+\arg{number} arguments (up to 9, as usual) and repeats \arg{code}
+indefinetely. So, at first sight, it's bad news. But the point
+is \arg{code} is supposed to launch the \com\breakwhile macro below sooner or
+later, i.e. stop the loop. Besides, on each iteration (barring the first), \arg{transformations}
+are applied to the arguments, and this means: the first argument is
+replaced by the first transformation, the second argument by the second
+transformation, etc. So there must be as many transformations as there
+are arguments, transformations themselves being just code that can
+make reference to the arguments. If you don't want to transform an
+argument, just repeat it in the transformation.
+
+\cslist{
+ !\breakwhile/code/
+ }
+This breaks the current while loop and executes \arg{code}, which can make
+reference to the arguments of the loop.
+
+\cslist{
+ !\changewhile/new arguments/
+ }
+This replaces the default \arg{transformations} defined with \com\newwhile
+and passes the \arg{new arguments} for the next iteration. There
+must be as many arguments as required by the loop. The original
+\arg{transformations} remain in force for the next iterations.
+
+\Example
+ % Transformations.
+\newwhile\largestsquare2{\numexpr(#1+1)}{#2}{%
+ \reverse\straighteniff{ifnum}{\numexpr(#1*#1)<#2 }
+ {The largest number whose square
+ is smaller than #2 is
+ \breakwhile{\the\numexpr(#1-1).}}}
+\largestsquare{1}{50}\par
+\largestsquare{1}{200}
+\Example/
+
+
+\description/
+
+
+
+
+\description{For statements on the fly}
+
+\cslist{
+ \dofor/list//parameter text/\barg{definition}/coda/
+ }
+This runs \arg{definition} on each occurrence of
+\arg{parameter text} in \arg{list}. The \arg{parameter text}
+is a real one, hence the braces around \arg{definition}.
+The \arg{coda} is executed if and only if the loop goes
+to its natural end, i.e. it is not terminated by one of
+the commands below. It must be present, even if you don't
+want one (in which case, leave it empty), and it can't make
+any reference to the arguments of the parameter text.
+A loop thus executed is absolutely
+not expandable. You can embed as many loops as you want
+(but don't forget to double the \verb/#/).
+
+\cslist{
+ \dofornoempty
+ }
+This is the same as above, except \arg{definition} is not executed
+when the \ital{first} argument is empty.
+
+
+\cslist{
+ \breakfor/code/
+ }
+This breaks the current loop and executes \arg{code};
+the \arg{coda} of the loop is not executed.
+
+\cslist{
+ \retrieverest/code/
+ }
+This also breaks the loop, but it retrieves the remaining
+arguments in the list and pass them as a braced argument
+to \arg{code}.
+
+\cslist{
+ \pausefor/code/
+ }
+This interrupts the loop and executes \arg{code}; the loop
+being interrupted means you're in the middle of the list, and
+you can process it. Such a pause must be terminated by a
+\com\resumefor if you don't want nasty internal code
+to surface.
+
+\cslist{
+ \resumefor\com\dofor
+ }
+This restarts the current loop. It is necessary to specify
+\com\dofor, because \com\resumefor is more general and is
+used to restart any kind of loop, especially those defined
+with \com\newfor (see next page).
+
+\Example
+\dofor{a,b,c,}#1,{[#1]}{}
+\Example/
+
+\Example
+\dofor{(a=13)(b=3)(c=54)(d=33)(e=22)}(#1=#2){%
+ \straighteniff{ifnum}{#2>50 }
+ {\breakfor{There's a number larger than 50: #1=#2.}}}
+ {No number larger than 50.}
+\Example/
+
+\Example
+\dofornoempty{dd,e,,acb,3,ee4,,,}#1,{%
+ \dofor{#1}##1{[##1]}{}...%
+ }{}
+\Example/
+
+\vskip\baselineskip
+
+The \com\dofor loop does not perform any kind of normalisation
+on the list. I.e. the list must be exactly designed to match
+the parameter text, including spaces and other unwelcome guests.
+
+The \com\dofor macro is useful for straightforward loops used once
+or twice in a document. But for fully fledged total-control
+fully expandable hey-that's-too-cool loops, you should use the
+\com\newfor construction.
+
+
+\description/
+
+
+
+
+
+
+
+
+
+
+
+
+
+\description{For statements: first steps}
+
+\cslist{
+ \newfor\comarg\barg{optional passed arguments},
+ \zilch\kern-4em/parameter text/\barg{definition}[/optional coda/]
+ }
+This creates a recursive \comarg\ that will consume all input
+with structure \arg{parameter text}. Let's forget
+\barg{optional arguments} for a while, since they're optional
+(albeit braced). Let's forget the optional coda as well. So
+it boils down to:
+
+\vskip\baselineskip
+\noindent\com\newfor\comarg\arg{parameter text}\barg{definition}
+\vskip\baselineskip
+
+\noindent so that basically \com\newfor works like \com\def.
+The \arg{parameter text} is a real parameter
+text as with \com\def, just like \barg{definition} is a real
+definition, hence the braces. The only difference is there must
+be at least one argument, because we need something to loop
+upon. I.e. \arg{parameter text} is at least \verb/#1/.
+
+Now you can launch \comarg\ on an argument which is made of as
+many occurrences of \arg{parameter text} as you wish, and on each
+occurrence \arg{definition} will be executed. So you've created
+a loop. And the good news is that this loop is fully expandable.
+
+It is your job to make sure that what is fed to \comarg\ has
+the correct argument structure.
+
+If \arg{coda} is specified, it is executed when the loop ends,
+if it ends naturally, i.e. by exhausting its input, and not
+by some of the loop-breaking commands on the next page. There
+can be no call to arguments of \arg{parameter text} in the
+\arg{coda}, e.g.
+
+\example
+\newfor\foo#1{...}[...#1...]
+\example/
+
+\noindent is impossible. (You'll get raw inner code.) Such
+reference to arguments in the \arg{coda} is possible only
+with passed arguments, as you'll see in two pages
+from here.
+
+(Note that if there's no \arg{coda}, any space will be gobbled
+after \barg{definition}. This is so because I thought it was better
+to be able to write \tcode{[\arg{code}]} after a space, e.g.
+a line end, than to stick it to \barg{definition}, even though
+that brings this little inconvenience, which is probably harmless
+since \com\newfor is very unlikely to end up anywhere in horizontal
+mode, i.e. in a paragraph.)
+
+Macro thus created can be freely embedded into one another.
+
+\Example
+\newfor\foo#1,{(#1)}
+\foo{a,b,c,}
+\Example/
+
+
+\cslist{
+ \newfornoempty
+ }
+The \com\newfornoempty is similar to \com\newfor, except \arg{definition}
+is not executed in the case the \ital{first} argument is empty.
+
+
+\Example
+\newfornoempty\foo(#1,#2){[#1/#2]}
+ [Input exhausted.]
+\edef\bar{\foo{(a,b)(c,d)(,e)(f,)}}
+\meaning\bar
+\Example/
+
+\Example
+\newfor\values#1=#2,{%
+ The value of #1 is #2.\par
+ }
+\def\setvalues#1{%
+ \ifsuffix,{#1}{\values{#1}}
+ {\values{#1,}}%
+ }
+\setvalues{A=12,B=45,}
+\setvalues{C=34}
+\Example/
+
+\Example
+\newstring, % \pdfliteral requires full expansion!
+\def\drawline#1{
+ 0 0 m % Initializes the path
+ \ifsuffix,{#1}{\drawlinefor{#1}}
+ {\drawlinefor{#1,}}
+ } % l = line
+\newfor\drawlinefor#1 #2,{#1 #2 l }[S]% S = draw path
+\pdfliteral{
+ q % kind of PDF \bgroup
+ 1 0 0 RG \drawline{20 10, 40 -15, 100 0,}
+ 0 1 0 RG \drawline{30 -15, 60 10, 130 0}
+ Q} % kind of PDF \egroup
+\Example/
+
+\description/
+
+
+
+
+
+
+
+
+\description{For statements: interruptions}
+
+\noindent (The commands on this page are the same as those
+introduced with \com\dofor; they're explained
+more thoroughly here.)
+
+\cslist{
+ !\breakfor/code/
+ }
+Used inside a loop created with \com\newfor, this
+interrupts it, gobbles the remaining input, and
+executes \arg{code}. If the loop had a \arg{coda},
+it is not executed. Any material between the \com\breakfor
+command and the end of the definition of the loop
+is gobbled. It is especially bad with conditionals,
+so you should use \com\afterfi, or better yet a
+\com\straightenif version.
+
+\Example
+\newfor\foo#1{%
+ \straighteniff{if}{\noexpand#1z}
+ {\breakfor{There is a `z'!}}
+ #1... % This will be gobbled.
+ }[There is no `z'...]
+
+\foo{abcdef}\par
+\foo{abzdef}
+\Example/
+
+\cslist{
+ !\retrieverest/code/
+ }
+This does the same thing as \com\breakfor, i.e. breaks the
+current loop, but it passes the rest of the material initially
+passed to the loop as a braced argument to \arg{code}. Arguments
+in that remaining material
+aren't extracted from their surrounding delimiters, if any.
+
+\Example
+\def\remainder#1{(And `#1' was still to come.)}
+\newfor\foo#1=#2,{%
+ \unless\ifnum#1=#2
+ \afterfi{% Thrilling...
+ \retrieverest{There is a false equation!
+ \remainder}}%
+ \fi}
+\foo{3=3,2=2,451=451,7=4,78=78,9=0,}
+\Example/
+
+
+\cslist{
+ !\pausefor/code/,
+ !\resumefor/loop command/
+ }
+The \com\pausefor command stops the loop and executes \arg{code}.
+That means that you're in the middle of the material being processed and
+you can act on it. It is useful if the material isn't totally
+regular. For instance, a typical Bib\TeX\ entry is a list of
+`\tcode{\arg{field}=\arg{value}}' pairs, with each pair
+terminated by a comma and the \arg{value} either between braces
+or quotes. Thus, you can't have a simple
+
+\example
+\newfor\bibfor#1=#2,{#1...#2}
+\example/{}{}
+
+\noindent to process the entry, because a \arg{value} may be delimited
+by quotes and still contain a comma, and quotes mean nothing to \TeX,
+so the comma will be mistaken for the delimiter. An oversimplified
+solution with \com\pausefor can be seen on the right. The loop actually
+works on the predictable part only (before the equal sign), is interrupted,
+the value is retrieved, and the loop is resumed.
+(Why one would want to process a Bib\TeX\ entry
+with \TeX\ in the first place is a question I can personally answer.)
+
+Once \com\pausefor is used, there must be somewhere down your code
+a \com\resumefor\comarg\ statement, to launch the loop again, otherwise
+you'll end up stumbling on some nasty internal code. It is impossible
+to know (in a perfectly expandable way) the loop we're currently in, hence
+the \comarg\ as a argument to \com\resumefor: it is the loop one wants to
+start again. Yes, it means you can also process the rest of the material
+with another loop, the consequences of which I leave it to you to ponder.
+
+
+\Example
+\newfor\bibfor#1={%
+ \pausefor{\getvalue{#1}}}
+\def\getvalue#1{%
+ \trim{#1}:
+ \ifnextnospace"{\getquotevalue}
+ {\getcommavalue}
+ }
+\def\getquotevalue"#1",{\showvalue{#1}}
+\def\getcommavalue#1,{\showvalue{#1}}
+\def\showvalue#1{%
+ {\it\trim{#1}}.\par\resumefor\bibfor}
+
+\bibfor{
+ Author = {John Doe},
+ Title = "Me, myself and I",
+ Year = 1978,}
+\Example/
+
+\description/
+
+
+
+
+
+
+
+
+
+
+\description{For statements: passed arguments}
+
+
+Suppose you want to retrieve the largest number in
+a list a numbers. The first example on the right shows
+you how to do so. But this solution won't work
+if you need the loop to be expandable, because there's
+a number assignment.
+
+\Example
+\newcount\largest
+\newfor\findlargest#1,{%
+ \ifnum#1>\largest
+ \largest=#1
+ \fi}
+ [The largest number is \the\largest.]
+
+\findlargest{45,33,1,4844,12,655,}
+\Example/
+
+That's why loops defined with \com\newfor can pass
+arguments from one iteration to the next. The number of those arguments
+are the \barg{optional passed arguments} in the description
+of \com\newfor two pages ago. So, a typical fully-fledged
+use of \com\newfor is:
+
+\example
+\newfor\myloop{2}#3=#4,{...#1...#2...#3...#4...}
+ [...#1...#2...]
+\example/
+
+\noindent which means that \com\myloop takes four arguments,
+two of which are actually passed arguments, the third and the
+four being in the recursive list that \com\myloop runs on.
+Besides, as you can see, passed arguments can appear in
+\arg{coda}.
+Now a call to \com\myloop looks like:
+
+\example
+\myloop{one}{two}{a=1,b=2,...}
+\example/
+
+\noindent where \tcode{one} and \tcode{two} are passed
+arguments. There can be up to 8 passed arguments (since there must
+be at least one argument to loop on), and if there are
+{\it n} of them, numbering of arguments in \arg{parameter text} must
+start at {\it n}+1, as in the above example.
+
+
+\cslist{
+ \passarguments/arg1//arg2/...
+ }
+Passed arguments are automatically retrieved from one iteration
+to the next. However, if you can't change them, they aren't very
+interesting. Hence this command: it passes \arg{arg1}, \arg{arg2}, etc.,
+to the next iteration, replacing the previous ones. There
+must be as many arguments to \com\passarguments as required
+by the loop, even if you don't want to pass new values for
+all (in which case, just pass the previous value).
+Beware: \com\passarguments ends the current iteration, just
+like \com\breakfor,
+and any remaining material in the definition of the loop
+is gobbled.
+
+Thus, the second version of our \com\findlargest command
+works as follows: it takes one harmless passed argument,
+and loops on the following list. Obviously, 45 is larger
+than 0, so it is passed as the new first argument; then,
+33 is not larger than 45, so nothing happen, and 45 is
+implicitly passed again as the first argument, and so
+on and so forth, until finally the \arg{coda} prints
+the largest number in the list. And, as illustrated
+by the \com\edef, everything expands nicely.
+
+\Example
+\newfor\findlargest{1}#2,{%
+ \straighteniff{ifnum}{#2>#1 }
+ {\passarguments{#2}}%
+ }
+ [The largest number is #1.]
+
+\edef\foo{\findlargest{0}{45,33,1,4844,12,655,}}
+\meaning\foo
+\Example/
+
+\description/
+
+
+
+
+
+
+
+
+\description{For statements: examples}
+
+
+Loops created with \com\newfor are somewhat tricky
+to get a hand on, so here are some examples. First
+of all, you might think that it would be nice to
+be able to define a loop whose argument structure
+is defined but not its replacement text, so that you
+can call it on similar lists but with different
+operations. For instance, a generic loop that works
+on all comma-separated lists. You can't do that exactly
+with \com\newfor, but you can easily use passed arguments
+to do something similar, e.g.:
+
+\example
+\newfor\commalist{1}#2,{#1{#2}}
+\commalist\tree{leaf,fruit,twig,}
+\commalist\scale{b minor,f sharp,whatever lydian}
+\example/
+
+\noindent with \com\tree and \com\scale defined to
+process one argument: \com\commalist itself has no real
+definition, and you don't have to bother about passed
+arguments (although you can still use them).
+
+\Example
+\newfor\sortnum{1}#2,{%
+ \subsortnum{#2}{}{#1}%
+ }[Sorted list: #1]
+\newfor\subsortnum{2}#3,{%
+ \straightenif{ifnum}{#1<#3 }
+ {\retrieverest{\passtosortnum{#2#1,#3,}}}
+ {\passarguments{#1}{#2#3,}}%
+ }[\passarguments{#2#1,}]
+\def\passtosortnum#1#2{\passarguments{#1#2}}
+
+\sortnum{}{5,12,-161,3,0,63,22,-45,}
+\Example/
+
+The first example sorts a list of numbers separated
+by commas. The first loop, \com\sortnum, takes a passed
+argument which contains the numbers already sorted (so
+it is empty at the beginning) and it runs on the list
+to be sorted. The second loop, \com\subsortnum, takes
+two passed arguments: the first one is the number under
+investigation, the second one is the list of numbers
+smaller than the number under investigation (so it is
+empty too at the beginning), and it is updated each
+time we find such a number as the third, non-passed
+arguments to \com\subsortnum, which is an element of
+the list of already sorted numbers as preserved in
+\com\sortnum's first passed argument... got that?
+
+Let's follow some iterations. The first call is:
+
+\example
+ % incoming arguments
+\sortnum{}5,12,-161,3,0,63,22,-45,
+\example/
+
+\noindent and it calls
+
+\example
+\subsortnum{5}{}{}
+\example/
+
+\noindent so that \com\subsortnum terminates immediately:
+it has no input. So it calls its coda:
+
+\example
+\passarguments{5,}
+\example/
+
+\noindent (where \tcode{5} is really the first argument following
+the empty second one). Since \com\subsortnum has terminated, this
+call to \com\passarguments is for \com\sortnum, hence the following
+iteration is:
+
+\example
+ % incoming arguments
+\sortnum{5,}12,-161,3,0,63,22,-45,
+--> \subsortnum{12}{}5,
+\example/
+
+\noindent Ah, something new. 12 is larger than 5, so the conditional
+is false. So \com\subsortnum passes the following to itself:
+
+\example
+\passarguments{12}{5,}
+--> \subsortnum{12}{5,}{}
+\example/
+
+\noindent and once again it terminates, hence:
+
+\example
+\passarguments{5,12,} % incoming arguments
+--> \sortnum{5,12,}-161,3,0,63,22,-45,
+ % incoming argument
+--> \subsortnum{-161}{}5,12,
+\example/
+
+\noindent and obviously -161 is smaller than 5, so the rest of the list
+is retrieved with \com\retrieverest and passed as the second argument of
+\com\passtosortnum. Once again, since this terminates \com\subsortnum,
+\com\passarguments in \com\passtosortnum is for \com\sortnum:
+
+\example
+\passtosortnum{-161,5,}{12,}
+ % incoming arguments
+--> \sortnum{-161,5,12,}3,0,63,22,-45,
+ % incoming arguments
+--> \subsortnum{3}{}-161,5,12,
+--> \subsortnum{3}{-161,}5,12,
+--> \passarguments{161,3,5,12,}
+--> \sortnum{-161,3,5,12,}0,63,22,-45,
+...
+\example/
+
+
+\noindent and so on and so forth.
+
+Replace the test with any other one and you
+have a generic sorting function, as in the example
+on the right, which sorts entries alphabetically
+or chronologically. It is possible to make things both
+cleverer and simpler. (The Lua code compares two
+strings, and it could very well have handled the
+\com\year version.)
+
+\Example
+\newfor\sortbooks{2}#3(#4),{%
+ \subsortbooks#1{#3(#4)}{}{#2}
+ }[\bgroup\it#2\egroup]
+\newfor\subsortbooks{3}#4(#5),{%
+ #1#2{#4}{#5}{#3}
+ }[\passarguments#1{#3#2,}]
+
+\def\alpha#1(#2)#3#4#5{%
+ \directlua{
+ if "#1"<"#3" then
+ tex.print("\noexpand\\firstoftwo")
+ else
+ tex.print("\noexpand\\secondoftwo")
+ end}
+ {\retrieverest{%
+ \passtosortbooks\alpha{#5#1(#2),#3(#4),}}}
+ {\passarguments\alpha{#1(#2)}{#5#3(#4),}}
+ }
+\def\year#1(#2)#3#4#5{
+ \straightenif{ifnum}{#2<#4 }
+ {\retrieverest{%
+ \passtosortbooks\year{#5#1(#2),#3(#4),}}}
+ {\passarguments\year{#1(#2)}{#5#3(#4),}}
+ }
+\def\passtosortbooks#1#2#3{\passarguments#1{#2#3}}
+
+\def\books{
+ Oblivion (2004),
+ Infinite Jest (1996),
+ Brief Interviews with Hideous Men (1999),
+ Girl with Curious Hair (1989),
+ The Broom of the System (1987),
+ The Pale King (2011),
+ }
+David Foster Wallace's books in alphabetical order:\par
+\passexpanded{\sortbooks\alpha{}}\books \par
+David Foster Wallace's books ordered by date:\par
+\passexpanded{\sortbooks\year{}}\books
+\Example/
+
+\vskip\baselineskip
+
+The next example is a palindrome detector: it returns
+true if the string it is fed is made of a string followed
+by itself reverse (which is not the exact definition of
+a palindrome, which is a string that is its own reverse,
+but we keep things simple).
+
+The first loop, \com\palincount, simply counts the number
+of characters in the string; it also reaccumulates it
+as its second argument, something that could be avoided
+if there was a wrapper macro. Once it is finished, it
+passes the original string along with half the number
+of characters to \com\palincheck, which simply accumulates
+in reverse this number of characters, by decreasing it
+on each iteration. Once this number is exhausted, it
+compares what it has accumulated to what there remains
+to be processed, and if both strings match, the original
+string is a palindrome.
+
+\Example
+\newfor\palincount{2}#3{%
+ \passarguments{\numexpr(#1+1)}{#2#3}%
+ }[\palincheck{\numexpr(#1/2)}{}{#2}]
+\newfor\palincheck{2}#3{%
+ \reverse\straightenif{ifnum}{\numexpr(#1-1)>0 }
+ {\retrieverest{\compare{#3#2}}}
+ {\passarguments{\numexpr(#1-1)}{#3#2}}%
+ }
+\def\compare#1#2{%
+ \ifstring{#1}{#2}{TRUE}{FALSE}%
+ }
+
+\edef\foo{\palincount{0}{}{abcdeffedcba}}
+\edef\bar{\palincount{0}{}{abcdff}}
+\meaning\foo, \meaning\bar
+\Example/
+
+
+\description/
+
+
+\bye
+
+
+
+
+
+
+
+
+
+
+\sortbooks{}{%
+ The Broom of the System (1987),%
+ Infinite Jest (1995),%
+ Girl with Curious Hair (1989),%
+ Brief Interviews with Hideous Men (1999),%
+ Oblivion (2004),%
+ The Pale King (2011),}
+
+\newfor\palin{2}#3{%
+ \passargs{\numexpr(#1+1)}{#2#3}%
+ }{\palincheck{\numexpr(#1/2)}{}{#2}}
+\newfor\palincheck{2}#3{%
+ \reverse\straightenif{ifnum}{\numexpr(#1-1)>0 }
+ {\retrievefor{\compare{#3#2}}}
+ {\passargs{\numexpr(#1-1)}{#3#2}}
+ }{}
+\def\compare#1#2{%
+ \ifstring{#1}{#2}{TRUE}{FALSE}%
+ }
+
+
++\edef\foo{\palin{0}{}{in noctes .. setconni}}+\foo