Formlett: For Letters To Multiple Receivers

Download as pdf or txt
Download as pdf or txt
You are on page 1of 9

FORMLETT: for Letters to Multiple Receivers

Zhuhan JIANG
School of Computing and Information Technology, University of Western Sydney, Vic-
toria Road, Parramatta NSW 2150, Australia. Email: z.jiang@uws.edu.au
(Last updated on 26 May 2003)
In this article, the author explains how to use a form-letter style formlett.sty,
designed for plain TEX and LaTEX or LaTEX2e. formlett.sty supports different
parameter input methods, parameter naming and defaulting mechanism, as well as
facilities for previewing parameter positions and printing labels. It is written for the
purpose of being powerful, robust and above all easy to use.

Introduction should not affect the resynchronisation for the next


In this modern world of ours, we often need to send a group. For instance we can keep the address of a re-
set of form letters, personalised or non-personalised, ceiver as a single group, as it often contains different
to many receivers at the same time. Or perhaps we number of (parameter) lines.
would like to have a collection of business letters or We often want to treat a particular group of let-
information brochures which we would like to call ter parameters somewhat uniformly. This can be
upon instantly whenever we need them. achieved by one of the following commands
Our purpose here is therefore to describe a com- \blockparas[<m>][<n>][<pre>][<post>]
prehensive implementation of such a macro system, \addressparas[<m>][<n>][<width>][<indent>]
handling form letters under TEX or LaTEX. The main They represent parameters in the <n>-th group,
objective is to provide an easy way to output many from the <m>-th to the last parameter of that group.
form letters with their own parameters, with or For \blockparas, tokens <pre> and <post> are
without the use of multiple files. There will be a those to be added in front and behind respectively
coherent and simple format for putting parameters each of the legitimate parameters mentioned above.
inside a form letter, with a number of helping facil- If <post> is \relax, it will then not be appended
ities for such as naming parameters and previewing at the end. Instead, each chosen parameter will be
their positions. A minimum support for printing put into a {}- pair before preceded by the token
mailing labels is also provided. <pre>. The reason for this exception is that while
<pre> and <post> are meant to be the front and
The concept of macros [1] for form letters is not new:
end macros for each selected parameter, in the case
there already exist macros in this connection such as
of <post> being \relax, we may regard <pre> as
merge, textmerg and address to name a few, see
acting upon each chosen parameter.
[2,3] for further details. Our stress here is therefore
laid on the ease to use, along with the power and The command \addressparas, however, uses
the robustness of the macros. \blockparas indirectly and will put the chosen pa-
rameters into a box of width <width>. If any se-
Format lected parameter is longer than <width>, then the
In this section, we always assume that the file line will be wrapped around, with all wrapped po-
formlett.sty or formlett.tex of version 2.3 tions being indented by an <indent>. This may
has already been input. Certain version of be used to deal with very long address lines. Inci-
formlett.sty can be obtained via anonymous ftp dentally, we may use \textbox or \addressbox or
from CTAN sites at macros /generic. \ADDRESSBOX to control the width of a single param-
eter. The general format reads
Essentially, each form letter, or letter format \textbox[<width]{<materials>}
or letter template, will be included between \addressbox[<width>][<indent>]{<materials>}
\beginletter and \endletter. Letter parameters \ADDRESSBOX{<width>}{<indent>}{<materials>}
that will be specified later on for each particular let- where the meaning of the macro parameters are self-
ter can be given by \paras[<m>][<n>], represent- explanatory.
ing the <m>-th parameter of the <n>-the parameter
group, at the positions you want them to be. Let For the macro parameters, we have for convenience
a cluster denote a complete collection of parameters provided the following defaults for those in the
that may be specified for a form letter. Then we can squared brackets
specify letter parameters group by group for a clus- <m>=1
ter such that inside each group the parameters are <n>=1
given sequentially and a termination of one group <pre>=\noindent

Jiang Z Formlett: for letters to multiple receivers 1


<post>=\par !
<width>= 8truecm
<indent>= 1.5em <addr-1-1>
This way, for instance, \paras[1][1] is equivalent <addr-1-2>
to any of the following commands ! letter two
\paras, \paras[1], \paras[][1], \endblockmode
\paras[1][], \paras[][] will produce the required form letter for each cluster
and the following three commands are also the same of parameters. The general rules are as follows:
\addressbox{one address line} • If a line contains \endblockmode or ! or +, then
\addressbox[8truecm]{one address line} everything else on that line is ignored and that
\addressbox[][1.5em]{one address line} line serves as an end/cluster/group marking line
Incidentally this is the reason why we used the sec- in the given priority order.
ond parameter <n> to represent the group num- • Leading and trailing empty lines before or after
ber: the defaults can often be dropped off more fre- a complete cluster will be ignored, unless ‘;’ is
quently. By default, all letter parameters specified there to force the next (empty) line as a starting
will be put into a group environment before putting parameter.
them into the form letter, unless \localparasfalse Obviously \blockmarks provides a more sensible de-
is issued beforehand. limiters for the blockmode, under which we could
have
To output a new letter entity, i.e a complete letter, \blockmarks\beginblockmode
we may use ....... force next empty line active
\moreletter
para-1-1;para-1-2;para-1-3; ... <para-1-2>
+para-2-1;para-2-2;... ------- - mark end of 1st group
+ ...
+para-n-1;para-n-2; ... ;para-n-m !
<para-2-2>
where ‘;’ separate parameters inside a same group,
<para-2-3>
‘+’ separates groups, ‘!’ ends a cluster of parameters,
======== end of cluster
and ‘...’ represent further letter parameters. These
three tokens are nothing special: we may change
<other clusters>
them to for instance ‘....’, ‘----’ and ‘====’ re-
\endblockmode
spectively by \blockmarks, and change them back
to ‘; + !’ by \defaultmarks. For more general A simpler and perhaps more often encountered sce-
case, use nario is to use names and addresses only. In this
\delimiters{<A>}{<B>}{<C>} case, there will be essentially only one group of pa-
where <A>, <B> and <C> are the new toks replacing rameters for each cluster. Thus we may use empty
‘; + !’ respectively. If we have to use these three lines to delimit the clusters, and use line by line
special characters or tokens inside our letter param- mode for the individual parameters. This way, each
eters, then use \pstr, \gstr and \cstr respectively block of consecutive nonempty lines in
instead. \beginlinemode
For the case of many clusters, we may enclose them, <name-1>
separated by any white spaces or empty lines, be- <address-1-1>
tween \beginpilemode and \endpilemode so that <address-1-2>
we don’t have to put \moreletter in front of each
cluster of parameters. <name-2>
<1st part of addr-2-1> %
We may also enter letter parameters line by line. In <continued part of line addr-2-1>
other words, we may essentially replace ‘;’ in the
\moreletter format by a normal line break. In this <name-3> % letter three
case, we shall put clusters of parameters between \endlinemode
\beginblockmode and \endblockmode. Thus the
will output a new complete letter, corresponding to
following commands
the specified letter parameters.
\beginblockmode
<para-1-1> Ideally, the name–address entries will be pro-
<para-1-2> duced by a database utility. Since they often
+ letter one contain special characters such as ‘#’ and ‘$’
explicitly, we may wish to change such charac-
<para-2-2> ters in the parameters to the normal printable

Jiang Z Formlett: for letters to multiple receivers 2


ones. For this purpose, we could use correspond- ing the positions of the letter parameters is to
ingly the pair \beginrawblockmode{<token>} use \preview. Under \preview, or \previewtrue,
with \endrawblockmode or the all parameters given by \paras[<m>][<n>] will be
pair \beginrawlinemode{<token>} with boxed with double borderlines, similar to 2 – 3 ,
\endrawlinemode. If <token> is not empty, the number <n>-<m> inside (corresponding to 2-3
then we use <token> in place of \endrawblockmode in the shown box) denotes the <m>-th parame-
or \endrawlinemode. In other words, <token> is ter of the <n>-th group. However, the parame-
the password to leave the raw text mode. Since ters given by \blockparas or \addressparas will
database utility will in general produce a fixed be boxed with triple borderlines. Moreover, the
number of <m> lines for each cluster of parame- macro parameters <pre> and <post> will also be
ters, we may use \begindatamode[<token>]{<m>} displayed explicitly. Since \addressparas is essen-
and \enddatamode (or <token>) in place of tially a special way of using \blockparas, it is high-
\beginrawlinemode and \endrawlinemode so that lighted via that for the \blockparas. In particular,
each <m> raw text lines, including the empty ones, \blockparas[3][6][\x][\y] for instance will dis-
will eject a form letter. play under \preview the following box
It is often desirable that a letter form or for- 6 – 3 (+): macro:->\x <<paras>> macro:->\y
mat and the actual parameters be kept in dif-
ferent files: it will help in archiving and retriev-
Sometimes we may want to have each given empty
ing form letters. Furthermore, if a letter is quite
letter parameter automatically replaced by a par-
long such that the TEX can’t hold it in the mem-
ticular default parameter. This can be easily
ory, then we have to keep the letter content in
done by using \loaddefaultparas inside your let-
a separate file. Essentially we need to save ev-
ter format, i.e. essentially between \beginletter
erything between \beginletter and \endletter
and \endletter, before any calling of the letter
into a separate file, say, letter.let, then later
parameters via \paras etc. Of course, the ef-
on use \inputletter{letter.let} to load in the
fect of \loaddefaultparas is nil unless a com-
letter format. Should one prefer to keep every-
mand \paradefaults is issued inside or (better
thing inside a single file, however, he may use
still) outside the letter format. We note that
\beginfile[password]{file.ext} and \endfile (or
\paradefaults takes the macro parameters in the
password) to create files such as letter.let men-
exact way as \paranames does. One note of caution:
tioned above as a temporary scratch file. We note
\paradefaults and \paranames always use the de-
that letter.let will not contain \beginletter
fault delimiters ‘; + !’ no matter how you changed
and \endletter as \inputletter will add them
them via \delimiters. This is to avoid unnecessary
properly for us. Also the extension .let is preferred
complications.
in this connection as it can indicate that this type
of format file should not quite be regarded as the We note that printing labels is no more than de-
normal TEX files. signing a special letter template. The mechanism
provided in formlett however is to pick a subblock
Likewise, it is also desirable to have a separate of parameters as the address. Basically all the form
address or general letter parameter file. For the letter output inside \beginlabels and \endlabels
address file, we remark that we have to keep will produce labels instead, taking the first parame-
the pairing \beginlinemode with \endlinemode or ter group as the address by default (see Appendix for
\beginblockmode with \endblockmode inside the more details). Incidentally, labels can be printed in
address file, if we are to use any of them for some single or double columns depending upon the choice
content of that file. Moreover, an extension .adr is of label width.
recommended for such files. Thus for a letter format
or template saved in letter.let, we may choose To conclude this section, we remark that if you want
letter.adr as the name for the related address file. to put \input filename into a letter parameter,
make sure that there is a nontrivial space follow-
After a letter format is completed for sometime, ing the filename. To be on the safe side, always use
one may have difficulty in recalling what those pa- \inputfile{filename.ext} instead. Also <!>, when
rameters should refer to when using the form let- output to screen, is an invitation to read the log file
ter again. For this purpose, we provide a simple for a warning message.
mechanism with \paranames and \showparas. To
be more precise, if one puts \paranames name-1-1; Example
...; <etc>! at the very beginning of the letter for-
The following is an example. If you are running
mat, then one can use \showparas outside to output
plain TEX, add \input formlett at the top. But if
a letter with its parameters replaced by their names.
you are running LaTEX, then just add at the top the
An alternative way, or rather a way of highlight- line

Jiang Z Formlett: for letters to multiple receivers 3


\documentstyle[formlett]{article} 0001 \paradefaults % optional 0025

\begin{document} 0002 To whom this may concern 0026

The line numbering on the right hand side is for +Sir or Madam;something;% 0027

reference only, as in the other occurrences later on. 061-225-9905! 0028

The example reads as follows. 0029

\beginletter 0003
\blockmarks 0030

\paranames % optional 0004


\beginrawblockmode{} 0031

\tt<<FULL NAME>>;% 0005 0032

\tt<<ADDRESS-etc>>;% 0006 Mrs L Stenson 0033

+\tt<<GIVEN NAME>>;% 0007 #1-20 Sunset Street 0034

\tt<<MISSING ITEM>>;% 0008 Hillside, Norway 0035

\tt<<PHONE NUMBER>>! 0009 ------ 0036

\loaddefaultparas % optional 0010 Louise 0037

0011 a Bible 0038

\NOPAGENUMBERS\parindent=0pt 0012 220-8888 0039

\noindent{\it\paras[1]}\par 0013 ========= 0040

\blockparas[2]\par\bigskip 0014 0041

0015 ...... 0042

Dear \paras[1][2],\par\medskip 0016 0043

We have been looking for 0017 Above empty line active 0044
\paras[2][2] for quite a while 0018
0045
without any luck, could you help 0019
\endrawblockmode 0046
us out? If so, please ring 0020

\paras[3][2]. \par\medskip 0021 We note the parameters contain special char-


Cheers!\hfill Michael\vfill\eject 0022 acters #. That is the reason why we used
\endletter 0023 \beginrawblockmode. Now suppose we have to
\preview \showparas 0024 wrap a very long address line, we could use
\addressbox to control an individual parameter.
The above is a typical letter format or form letter. The following is a typical case
Command \preview in the last line gives
1 – 1
\defaultmarks 0047

\moreletter 0048
1 – 2 (+): macro:->\noindent <<paras>> macro:->\par S Wales,;% 0049

\addressbox[2in][1em]{% 0050
2 – 1
Dear , University of Manchester Institute 0051

2 – 2 of Science and Technology, This is 0052


We have been looking for for quite a while
a long address line: it will be 0053
without any luck, could you help us out? If so,
2 – 3
wrapped up automatically.}% 0054
please ring . +;a \TeX\ package \gstr\ manual and 0055

Cheers! Michael many more (\cstr)! 0056

and, the name of the parameters are displayed via which is manifested in the following output
\showparas as follows
S Wales,
<<FULL NAME>> University of Manchester Institute
<<ADDRESS-etc>> of Science and Technology, This
Dear <<GIVEN NAME>>, is a long address line: it will be
We have been looking for <<MISSING ITEM>> for wrapped up automatically.
quite a while without any luck, could you help us Dear Sir or Madam,
out? If so, please ring <<PHONE NUMBER>>.
We have been looking for a TEX package + manual
Cheers! Michael and many more (!) for quite a while without any
luck, could you help us out? If so, please ring 061-
In other words, we can have a good understanding 225-9905.
about what a letter format does without reading its
source code, which will be very handy for archiv- Cheers! Michael
ing and retrieving letter templates. To provide de-
faults for letter parameters and output new letters Please note that the default parameters have been
via blockmode, we may add used there. In the case of putting only name and

Jiang Z Formlett: for letters to multiple receivers 4


address into a form letter, we may typically use for two dimensional case, where m and n are some
linemode via e.g. non-negative integers representing row and column
\beginlinemode 0057
numbers respectively. The first element, if neces-
Z Jiang 0058
sary, will be used to denote the length of that raw.
UNE, Arimdale 0059
Thus, \ABC1*0~ for instance will denote the num-
0060
ber of elements in the first raw of a two dimensional
T Ribbons 0061
array ABC.
UMIST, Manchester 0062 Let us now look at how a mechanism of default-
\endlinemode 0063 ing macro parameters is formulated. For this pur-
\end{document} 0064 pose, we first define a stack STK and its stack pointer
If one saves lines 4-22 to file myletter.let, lines \STKcount by
25-63 or simply lines 57-63 to file myletter.adr, \def\make@STKcount{\csname newcount\endcsname
then we can for instance produce via LaTEX the form \STKcount\global\STKcount=0\relax}
letter for multiple receivers by \ifx\STKcount\undefined@\def\next{%
\documentstyle[formlett]{article} \make@STKcount}\else\def\next{}\fi\next
\begin{document} \long\def\push#1{\global
\inputletter{myletter.let} \advance\STKcount1\relax
\showparas \preview \expandafter\gdef\csname STK\the
\paradefaults To whom it may concern! \STKcount\string~\endcsname{#1}}
\inputfile{myletter.adr} \def\popnil{\expandafter\let
\beginlabels % 1st parameter group as address \expandafter\temp@macro\csname
\inputfile{myletter.adr} % for labels STK\the\STKcount\string~\endcsname
\endlabels \ifnum\STKcount>0\global\expandafter
\end{document} \let\csname STK\the\STKcount
If one puts commands \beginlables and \string~\endcsname=\undefined@
\endlabels at e.g. immediately after line 2 \global\advance\STKcount-1%
and 63 respectively, then one gets all the \else
posting labels instead. If one puts commands \def\temp@macro{}\global\STKcount=0%
\beginfile{scratch.adr} and \endfile there \fi\relax }
respectively, then by adding after \endfile the \def\pop{\popnil\temp@macro}
commands The first four lines of code will ensure that the
\inputfile{scratch.adr} stack pointer will not be flushed if this useful sub-
\beginlabels \inputfile{scratch.adr} \endlabels set of macros is loaded again by for instance an-
one gets both form letters and the labels. If other style file in the middle of a TEX document.
one insists on not writing out auxiliary scratch With the above code, we can stack away anything
files, then use \input formlett.sty \initstyle by \push{anything} and later use \pop to recall
[styles]{article}{preamble} to replace them or \popnil to remove one element from the
\documentstyle [formlett, styles]{article} stack.
preamble \begin{document}, which will be valid for So, how can we make defaults for certain empty
LaTEX but ignored for TEX , and will enable one to macro parameters? The simplest case is perhaps
use \labelsquit at the end to read in the current \long\def\get@nepara[#1][#2]{{%
document again with all the letters there converted \def\next@{#2}%
into the corresponding labels. If you only want to \ifx\next@\empty\push{#1}\else
execute certain commands the first time round (i.e. \push{#2}\fi}\ag@in}
before \labelsquit re-reads the file again), use \long\def\get@para\left@#1\right@{%
\firstread{commands} for this purpose. \def\check@{%
\ifx[\next@
Macros \def\full@####1{\get@nepara[#1]####1}%
One of the main technical features of this set of \else
macros is the extensive use of arrays, both one di- \def\full@{\get@nepara[#1][#1]}\fi
mensional and two dimensional. The one dimen- \full@}%
sional array STK that we use is essentially an user- \futurelet\next@\check@}
defined stack, while the two dimensional arrays LET Basically, \get@onepara[<A>][<B>] will push the
and DEF are more like structure or record in other default <A> to the stack STK unless <B> is nonempty.
programming languages. First let us make clear that And \get@para\left@<A>\right@ will look at the
an array (or stack) of name, say ABC, will contain el- next token to be read, if it is character ‘[’, then
ements \ABCm~ for one dimensional and \ABCm*n~ reads in a macro parameter in the form of [<B>]

Jiang Z Formlett: for letters to multiple receivers 5


and then push <B> to the stack STK, otherwise push \or\global\p@r@three=\expandafter{\t@macro}%
the default <A> to that stack. For the more general \or\global\p@r@four=\expandafter{\t@macro}%
case, we need to define \or\global\p@r@five=\expandafter{\t@macro}%
\long\def\do@nepara \or\global\p@r@six=\expandafter{\t@macro}%
\left@#1\right@#2\p@r@end{% \or\global\p@r@seven=\expandafter{\t@macro}%
\gdef\p@r@data{#2}\global\advance \or\global\p@r@eight=\expandafter{\t@macro}%
\p@r@count1\get@para\left@#1\right@} \or\global\p@r@nine=\expandafter{\t@macro}%
\def\ag@in{\ifx\p@r@data\empty \else
\def\next@{\relax\getp@r@s\run@CMD}% \errmessage
\else\def\next@{\expandafter\do@nepara {Parameter capacity exceeded.}%
\p@r@data\p@r@end}% \fi \global\expandafter\let
\fi\next@} \csname STK\the\STKcount
\def\run@CMD{\csname STK\the\STKcount \string~\endcsname=\undefined@%
\string~\endcsname} \global\advance\STKcount-1%
\newcount\p@r@count \global\advance\temp@count-1\relax
\long\def\st@ckparas#1\p@r@end{% \fi
\global\p@r@count=0% \ifnum\temp@count>0\repeat}}
\gdef\p@r@data{#1}\ag@in} We are now ready to use the above mechanism to
so that \st@ckparas\left@<A>\right@... default macro parameters for some already defined
\left@<B>\right@... \p@r@end will look for pa- macros. Suppose we have already defined a macro
rameters enclosed in [] one by one, exhausting all \crudemac[<A>][<B>] which takes two macro pa-
the defaults paired by \left@ and \right@. If rameters <A> and <B>, and we want to define a new
future tokens inside [] are not found, or empty, macro \smartmac which behaves like \crudemac but
the default tokens inside the corresponding pair will default the macro parameters <A> and <B> to for
\left@\right@ will be used. The new or default to- instance 9 and 88 respectively. For this purpose, we
kens will be pushed to the general-purpose stack STK may define \smartmac via
for a later use, while \p@r@count records the total \def\smartmac{\push{%
number of the default macro parameters. We note \edef\next@@{\noexpand
that on exit of \st@ckparas, the control is passed \crudemac[\the\p@r@one][\the\p@r@two]}%
to \runCMD. \popnil\clrp@r@s\next@@}\st@ckparas
Once all macro parameters are pushed to the stack, \left@9\right@\left@88\right@\p@r@end}
we may transfer them to separate toks \p@r@one to This way, all the followings
\p@r@nine (an easier-to-use format) defined by \crudemac[9][88], \smartmac[9][88],
\newtoks\p@r@one\newtoks\p@r@two \smartmac, \smartmac[], \smartmac[][],
\newtoks\p@r@three\newtoks\p@r@four \smartmac[9], \smartmac[9][], \smartmac[][88]
\newtoks\p@r@five \newtoks\p@r@six are the same under the assumption that we shall not
\newtoks\p@r@seven\newtoks\p@r@eight use characters ‘[’ and ‘]’ for the macro parameters
\newtoks\p@r@nine themselves, and that \crudemac will not change any
\def\clrp@r@s{\global\p@r@one={}% \catcode inside. The reason for this latter condi-
\global\p@r@two={}\global\p@r@three={}% tion lies in the fact that when \smartmac looks at
\global\p@r@four={}\global\p@r@five={}% the next character, the character is in a sense al-
\global\p@r@six={}\global\p@r@seven={}% ready read. If \crudemac changes the \catcode of
\global\p@r@eight={}\global\p@r@nine={}} that particular character, then the one that is al-
where \clrp@r@s clears all the parameter toks. We ready read via \futurelet will have a misleading
can then retrieve parameters from the stack STK to \catcode. If one has to change \catcode inside
the parameter toks via \getp@r@s with the following but wants to avoid this possible misbehavior, al-
code ways put full number of empty brackets ‘[]’ for the
\newcount\temp@count
defaults, or put a \relax immediately afterwards.
\def\getp@r@s{\temp@count=\p@r@count
Better still, make the last parameter to appear in a
{\loop
mandatory ‘{}’ form rather than the ‘[]’ form via
the #{ mechanism [1], so that those square brackets
\ifnum\temp@count>0
can be dropped off.
\expandafter\let\expandafter
\t@macro\csname STK\the\STKcount For example, we as a by-product also defined a 100%
\string~\endcsname verbatim mode by
\ifcase\temp@count \begin@@rawlist[A][B ][C ][D ][E ][F ]G
\or\global\p@r@one=\expandafter{\t@macro}% <general text>
\or\global\p@r@two=\expandafter{\t@macro}% \endrawlist

Jiang Z Formlett: for letters to multiple receivers 6


where, for the line numbering of the raw text, A, \temp@toks={#2\s@fetymarkI#1\s@fetymark}%
..., G represent respectively the initial value, incre- \expandafter\p@rse\the\temp@toks }%
ment step, number of digits, font, horizontal po- The \first@half will contain the tokens upto but
sition of text, horizontal shift of numbering, and excluding the substring #1, while the \second@half
the password to leave raw text mode. Inciden- will contain the tokens after the first appearance
tally, \linecount records the current line number- of #1. Should #2 not contain string #1 at all,
ing count. Our purpose is to define \beginrawlist then \first@half is the whole string #2 whereas
so that its format is \second@half is empty.
\beginrawlist[A][B ][C ][D ][E ][F ]{G}
in which A to F are optional while {G} is manda- The small macros such as the above one and
tory even though G can be empty — implying the stack utilities, though built for the main pur-
\endrawlist is the password to leave the raw-text pose of formlett, provide also a good ‘infrastruc-
mode. For this purpose, we first define ture’ for other house-keepings. One of the side-
\def\begin@rawlist[#1][#2][#3][#4][#5][#6]#{% kicks of this type is our macro for commenting
\begin@@rawlist[#1][#2][#3][#4][#5][#6]}% out blocks of text inside a TEX file. Basically,
to make ‘{}’ pair compulsory for #7, then we provide \begincomment{password} will set all characters of
the defaults for A to F as \linecount, 1, 0, \tiny, code 0 to \MAX@CHR@CODE (=255 by default) to
0pt and 0pt respectively via catcode 11 or 12, and look for the password, or
\def\beginrawlist{\push{% \endcomment in the absence of a password, to quit
\edef\next@@{\noexpand\begin@rawlist the comment mode. In comparison to a very com-
[\the\p@r@one][\the\p@r@two][\the\p@r@three]% pact macro comment.sty (currently at version 3.0)
[\the\p@r@four][\the\p@r@five][\the\p@r@six]}% written by Victor Eijkhout, quitting comment mode
\popnil\clrp@r@s\next@@}% end of push via a password here seems more flexible.
\font\tiny@rm=cmr5% As for the other macros in formlett, it is difficult
\edef\temp@macro{% to explain them without printing out all of them. So
\noexpand\left@\the\linecount\noexpand\right@ instead, we shall explain simply one of the strategies
\noexpand\left@1\noexpand\right@ in parsing the letter parameters. Suppose W is a list
\noexpand\left@0\noexpand\right@ of parameters separated by ‘+’ and ended by ‘!’, i.e.
\noexpand\left@\noexpand\tiny@rm W is like <A>+<B>+...+<S>!. Then it will be easy
\noexpand\right@ to parse all the parameters one by one (to a stack for
\noexpand\left@0pt\noexpand\right@ instance) if we can know whether there is precisely
\noexpand\left@0pt\noexpand\right@}% one parameter left over. To detect it, we use
\expandafter\st@ckparas\temp@macro\p@r@end}% \newif\ifl@stline
Likewise, we could also similarly define \long\def\testl@stline
\printfile[...]{filename.ext} so that ‘[...]’ #1+#2!#3\s@fetymark{%
takes a same defaulting scheme. \def\next{#2}\ifx\next\empty
\l@stlinetrue\else\l@stlinefalse\fi
There are several tiny but very useful macros in \def\next{#3}\def\nextsample{+!}%
formlett which are used again and again. One of \ifx\next\nextsample\l@stlinefalse\fi}
such macros is for testing if one string contains an-
Then the command \testl@stline
other string. The following \test@str tests if string
W +!\s@fetymark will set \l@stlinetrue if there
#1 is contained in string #2
is only one parameter left in W , and will set
\newif\iftemp@if \newtoks\temp@toks
\l@stlinefalse if otherwise.
% return \temp@iftrue if yes,
% \first@half,\second@half are global Finally, for those wizard users who want to do
\long\def\test@str#1#2{% everything their own way, we just note that if
\long\def\strip@endmark##1\s@fetymarkI for instance the 3rd letter parameter of the 2nd
#1\s@fetymark{\gdef\second@half{##1}}% group of a cluster is given as <A>, then \LET2*3~
\long\def\strip@markI##1\s@fetymarkI will contain \b@group\relax<A>\e@group right af-
\s@fetymark{\gdef\first@half{##1}}% ter a cluster is read in. \DEF2*3~, on the other
\long\def\p@rse##1#1##2\s@fetymark{% hand, contains the corresponding default parame-
\gdef\first@half{##1}% ter in the same fashion. Furthermore, the command
\gdef\second@half{##2}% \checkparas[m][n]{LET} will copy the content of
\ifx\second@half\empty \paras[m][n], minus the ‘wrapping’ extra tokens
\strip@markI##1\s@fetymark\temp@iffalse \b@group\relax and \e@group, to \cachedata and
\else set \ifemptyparas to true or false depending on
\strip@endmark##2\s@fetymark\temp@iftrue whether the content is empty or not. This way,
\fi}% a user may even change the characteristics of his

Jiang Z Formlett: for letters to multiple receivers 7


letter template by first testing the content of the
\checkparas[m][n]{T } mth parameter of
supplied individual parameters. However, we note nth group copied
that if \loaddefaultparas is executed, then the to \cachedata;
LET array, when some of its elements are not sup- \ifemptyparas is true
if element is empty; T is
plied, will contain the corresponding elements of the often LET or DEF
DEF array. Hence care must be exercised under such \moreletter F use parameters F to out-
circumstances, when interpreting the \cachedata put a new letter
generated by \checkparas[m][n]{LET}. If neces- \paranames R use R as parameter
names
sary, we may use \delparadefaults to delete cur- \paradefaults R use R as default
rent default parameter array DEF so as to conduct parameters
\checkparas{LET} more precisely. So if anyone \delparadefaults delete default parameters
\delimiters{P }{G}{C} use P , G, C as delimiters
wants to manipulate furthermore letter parameters \defaultmarks use ‘; + !’ as delimiters
inside a letter template, he or she will now at least \blockmarks use ‘....’, ‘----’, ‘====’
know where to look at. as delimiters
\preview highlight parameter
positions
References \showparas display parameter
names, if any
[1]. Knuth D E, The TEXbook, Reading, Mass., \inputletter{f ile.ext} input letter content
Addison-Wesley, 1992. \inputfile{f ile.ext}
n input f ile.ext
[2]. Piff M, Text merges in TEX and LaTEX, TUG- \beginletter delimiters for letter con-
n \endletter tent (template)
boad, 13(4):518, 1993.
\beginpilemode normal letter parameters
[3]. Damrau J and Wester M, Form letters with cluster-wise
n \endpilemode
3-across labels capacity, TUGboat, 13(4):510, \beginblockmode for line-by-line blocks of
1991. \endblockmode parameters, empty lines
n active within each cluster
\beginlinemode for line-by-line parame-
Appendix \endlinemode ters, empty lines delimit
clusters
In the followings, we give a brief summary of the n
\beginrawblockmode{T } raw text mode;
new commands given by formlett version 2.3. \endrawblockmode nonempty T replaces
\endrawblockmode to
Let m and n be numbers, p, q and r be dimen- n mark end
sions, A, B, P , G, C and T be tokens, and X be a \beginrawlinemode{T } raw text parameters and
n \endrawlinemode active spaces etc
box. Furthermore, we shall denote by R a full set of \begindatamode[T ]{m} m raw text lines for one
letter parameters ended by ‘!’, with ‘;’ separating n \enddatamode form letter
parameters inside a same group and ‘+’ separating \begincolumns[a][b] a-columns separated by
n \endcolumns distance b
different parameter groups. We moreover denote R \begincomment{T } comment out lines,
by F , when ‘; + !’ there can be replaced by ‘P \endcomment nonempty T replaces
G C’ respectively if \delimiters{P }{G}{C} is is- \endcomment to mark
last full line for comment
sued. In the commands tabulated below, the macro n
\beginfile[T ]{file.ext} write text verbatim to
parameters contained in squared brackets support \endfile file file.ext (empty im-
default. In particular, the defaults are m=1, plies scr@tch@.tex),
n=1, p=8truecm, q=1.5em, r=3pt, A=\noindent, nonempty T replaces
\endfile to mark last
B=\par, \previewfalse, \localparastrue and full line
\nodefaultsfalse. \PAGENO=1 page number reset to 1
\NOPAGENUMBERS no page numbers
\textbox[p]{text} text into box of width p
\boxmore[r]{X} add borderline to box X
at a distance r
\addressbox[p][q]{text} text into box of width
p, with wrapped options
\paras[m][n] mth parameter of nth indented by q
group \previewfalse given parameters instead
\blockparas[m][n][A][B] mth to the last param- of highlighted boxes will
eter of nth group, each be shown
preceded by A and fol- \localparastrue letter parameters put
lowed by B, wrapped by into {} before displayed
{} if B=\relax \nodefaultsfalse take defaults for empty
\addressparas[m][n][p][q] mth to the last pa- letter parameters
rameter of nth group, \previewtrue cf. above
each put into a box of \localparasfalse
width p with indent q for \nodefaultstrue
wrapped portions
\loaddefaultparas fill empty parameters
with defaults Table continues in the next page

Jiang Z Formlett: for letters to multiple receivers 8


n
\beginrawlist[a][b][c][d][e][f ]{g}
\endrawlist
verbatim listing, line
defaults: count from a, step b,
a=\linecount, digits c, font d, text po-
b=1, c=0, sition e, numbering shift
d=\tiny@rm, f , end mark g
e=0pt, f =0pt,
g=\endrawlist
\printfile[a][b][c][d][e][f ]{file.ext}

verbatim listing of
defaults: c=6 etc
n file.ext
\beginlabels[a][b][c][d][e][f ]
\endlabels
form letters become la-
defaults: bels: address taken from
a=20pt, cth to last parameter of
b=\tt\raggedright, dth group, with width e,
c=1, d=1, indent f , borderspace a
e=2.6in, f =2em and font toks b
\firstread{T } toks T will not be read
if the file is re-read via
\labelsquit
\initstyle[a]{b}{c} initiation for
\labelsquit,with styles
a, documentstyle b and
preamble c
\initclass[a][o]{b}{c} similar to \initstyle (o
is LaTEX2e options), but
retains native LaTEX2e
when applicable
\labelsquit[a][b][c][d][e][f ]{file.ext}

quit after converting let-


defaults: ters to labels by reading
see that for \beginlabels the current document or
file.ext
\newarray\abc make array named abc
along with \abc and
\checkabc
\delarray\abc delete array named abc
\abc(m)={T } assign tokens T to
\abc(m); \abc(m) ≡
\abc(m1 , ..., mk ) for
Pk
m=1 + 1
(mi − 1) ∗
\dataheightk−i
\abc(m) value of \abc(m), if not
followed by ‘=’
\dataheight current array dimension:
cf. \abc(m)
\readarray{N }{a1 & .. &an } equivalent to \N(1)=a1 ,
.., \N(n)=an
\checkabc(m) copy \abc(m) to
\cachedata; set
\ifemptydata to
true/false accordingly
\readstyles{f1 , ..., fn } read files f1 to fn with
default extension .sty;
@’s catcode set to 11 dur-
ing input

Jiang Z Formlett: for letters to multiple receivers •End of Document• 9

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy