21-Dec-87 09:30:52-PST,12519;000000000000 Return-Path: <@RELAY.CS.NET:phcalamai@water.waterloo.edu> From: "Paul H. Calamai" Subject: Re: LaTeX list environment question Steve Buyske : > > > I would like to make a construct a list environment so that I can > have labels that might require two line. Something like > > Professional Something silly, something else silly, some more > Associations: silly things, and so on. > > If I put the label in a \parbox, no matter how I fiddle around, I get > something like: > > Professional Something silly, something else silly, some more > Associations: > silly things, and so on. > > with an ugly extra line. Can anyone give me some advice? > > My apologies if this is an easy question, but I'm new to LaTeX and > desperate to get my C.V. done. > Here is a tex file that will do what you want: % relate_macros.tex 1987 Jun 10 E. Ledoux % Instructions for use are located at the end of this file. % \makeatletter % \newdimen\relateleft \relateleft=\leftmargin % space before label \newdimen\relateright \relateright=\leftmargin % min. space after label \newbox\RELbox \newcount\RELcount \RELcount\z@ \newdimen\RELoldmax \newdimen\RELnewmax % \def\relate{\@ifnextchar [{\RELcontd}{\global\advance\RELcount\@ne \expandafter\RELcontd\expandafter [\romannumeral \the\RELcount]}}% % \def\RELcontd[#1]{\def\RELlabel{#1}% \expandafter\let\expandafter\RELmax\csname RELold@#1\endcsname \ifx\RELmax\relax \RELoldmax0.20\hsize \else \RELoldmax\RELmax \fi \list{}{\labelwidth\RELoldmax \itemindent\z@ \leftmargin\RELoldmax \advance\leftmargin\relateleft \advance\leftmargin\relateright \let\makelabel\RELmakelabel}}% % \def\RELmakelabel#1{\@ifundefined{RELnew@\RELlabel}{\RELnewmax\z@}% {\expandafter\RELnewmax\csname RELnew@\RELlabel\endcsname}% \setbox\RELbox\hbox{\vtop to0pt{\let\\\cr \halign{##\hfil\cr#1\cr} \vss}}% \ifdim\wd\RELbox>\RELnewmax \RELnewmax\wd\RELbox\fi \expandafter\xdef\csname RELnew@\RELlabel\endcsname{\the\RELnewmax}% \hskip\labelsep \hskip-\relateright \hbox to\z@{\box\RELbox\hss}\hfill}% % \def\endrelate{\toks\z@\expandafter{\csname RELold@\RELlabel\endcsname}% \immediate\write\@auxout{\gdef\the\toks0{\csname RELnew@\RELlabel\endcsname}}% \endlist}% % \makeatother \endinput HOW TO USE IT This LaTeX macro file defines a "relate" environment, which is basically a more intelligent "description" environment. To use it, place \input {path}relate somewhere before \begin{document}. Here's an example of relate environment usage: \begin{relate} \item[Spot] Spot is a dog. See Spot run. \item[Spock] Spock is a Vulcan. See Spock think. \item[Cigarette\\Smoke] Smoke is a health hazard. The Surgeon General recommends ... smoked. \end{relate} This produces output that looks like this: | preceding text | +-----------------------------------------------------------+ Spot Spot is a dog. See Spot run. Spock Spock is a Vulcan. See Spock think. Cigarette Smoke is a health hazard. The Smoke Surgeon General .................... ........ smoked. |<---->| |<---->| \relateleft \relateright |<---- left margin ---->| The relate environment behaves very much like the description environment except: 1. \item labels may be multi-line. For example, \item[Cigarette\\Smoke] produces a two-line label, with "Cigarette" on one line and "Smoke" on the following line. [BUG: You get strange output if your label has more lines than the associated text.] 2. Labels don't intrude into the text, like long labels do in the description environment. Relate automatically calculates the width of the widest label in a relate environment and adjusts the "left margin" of the text appropriately. This is done using the .aux file, similar to LaTeX section, page number etc. references, so margins will not be correct until the second LaTeX run after a change to a label is made. \relateleft and \relateright are horizontal space parameters; the left margin for a relate environment will be equal to \relateleft + maximum-width + \relateright where maximum-width is the width of the widest label. The default value of both \relateleft and \relateright is \leftmargin (about 25 points when using 10-point fonts). \relateleft and \relateright can be changed using \setlength, eg. \setlength{\relateleft}{0.5in} \setlength{\relateright}{0.3in} This can be done immediately after \input-ing relate_macros. Normally, each relate environment is autonomous in the sense that only labels in that environment determine the left margin for that environment. However, different relate environments within the same document can be "linked" so that they have the same left margin. For example, ... \begin{relate}[apple] \item[anything] ... ... \end{relate} ... \begin{relate}[apple] \item[whatever] ... ... \end{relate} ... The left margins in these two relate environments will be the same because they were "linked" by placing the same "label" ("apple" in this example) in square brackets after \begin{relate}. You can link any number of relate environments in the same document; they need not be adjacent. Labels should consist entirely of lower and uppercase letters. If you get strange margins when using relate, just re-latex your document. The left margins will be recalculated and should be correct on the second run. By the way, you can nest relates within one another and within other list environments as well. HOW IT WORKS relate_macros.tex is described below: \makeatletter This allows '@' to be used in control sequences, plus allows access to the efficient \z@ (zero), \@ne (one), and other TeX and LaTeX hacks. \newdimen\relateleft \relateleft=\leftmargin % space before label \newdimen\relateright \relateright=\labelsep % min. space after label Defines and sets the default values of \relateleft and \relateright. \newbox\RELbox \newcount\RELcount \RELcount\z@ \newdimen\RELoldmax \newdimen\RELnewmax \RELbox temporarily holds a label so that it can be measured. \RELoldmax will hold the width of the widest label for this (and similarly labelled) enviroments as calculated in the last run, for the duration of each relate environment. Similarly, \RELnewmax holds the width of the widest label for this (and similarly labelled) relate environments as calculated in this run, but \RELnewmax is updated from \RELnew@xxx and stored to \RELnew@xxx at every \item in the environment (see below). For a relate environment labelled, say, "apple", a global control sequence named \RELnew@apple will be used to keep track of the width of the widest label of all "apple" relate environments. Inside each "apple" env. \item, \RELnew@apple is copied to \RELnewmax. \RELnewmax is updated if necessary as the width of each label is computed. When the \item ends, \RELnewmax is copied back to \RELnew@apple, in case there are more "apple" environments. When the entire environment ends, a line like: \gdef \RELold@apple {28.74pt} is written to the .aux file, where 28.74pt would be the value of \RELnewmax, the width of the widest label so far encountered in this and previous relate environments. At the beginning of every run (at \begin{document}, in fact), the .aux file is \input automatically by LaTeX. Assuming the previous run contained several relate environments labelled "apple", \RELold@apple will be defined (and redefined by each "apple" environment in the previous run) to be the width of the widest label in all "apple" environments in the previous run. Assuming no labels changed since then, this value will be the correct maximum label width. (If this is the first run, \RELold@apple is not defined and the arbitrary value of 0.20\hsize, one third the width of the page, is used instead.) In each "apple" relate environment, \RELold@apple is copied to \RELoldmax, which is used to position labels within a left margin of width \relateleft + \RELoldmax + \relateright. \def\relate{\@ifnextchar [{\RELcontd}{\global\advance\RELcount\@ne \expandafter\RELcontd\expandafter [\romannumeral \the\RELcount]}}% \RELcount is a counter used to create unique relate environment labels for when the user doesn't supply one (like "apple" in the above example). \begin{relate} simply invokes \relate; if an argument in square brackets is present (eg. [apple]), then \RELcontd ("relate continued") is called with that argument. Otherwise, \RELcount is incremented and a unique label is formed by converting the value of \RELcount to lowercase roman numerals (ie. "i", "ii", "iii", "iv", ...). \def\RELcontd[#1]{\gdef\RELlabel{#1}% \RELlabel holds the environment label for use by \endrelate. \expandafter\let\expandafter\RELmax\csname RELold@#1\endcsname \ifx\RELmax\relax \RELoldmax0.20\hsize \else \RELoldmax\RELmax \fi If \RELold@apple (assuming "apple" relate environment label) has been defined (presumably in the .aux file), set \RELoldmax to that value, otherwise set \RELoldmax to the arbitrary value of 0.20\hsize. \@ifundefined{RELnew@#1}{\global\RELnewmax\z@}% {\expandafter\global\expandafter\RELnewmax\csname RELnew@#1\endcsname}% If \RELnew@apple has been defined, then set \RELnewmax to that value, otherwise set \RELnewmax to zero. \list{}{\labelwidth\RELoldmax \itemindent\z@ \leftmargin\RELoldmax \advance\leftmargin\relateleft \advance\leftmargin\relateright \let\makelabel\RELmakelabel}}% Start a \list. Set \labelwidth to zero; labels will really have zero width anyway. Set the \leftmargin to \RELoldmax + \relateleft + \relateright. (This is LaTeX's idea of left margin; see p. 113 in the LaTeX manual.) Set \labelwidth to the maximum label width -- the label will be right- justified within a box of this width by \RELmakelabel. \RELmakelabel will be used to make labels. \def\RELmakelabel#1{\@ifundefined{RELnew@\RELlabel}{\RELnewmax\z@}% {\expandafter\RELnewmax\csname RELnew@\RELlabel\endcsname}% If \RELnew@apple is undefined, define \RELnewmax as zero, otherwise define it as the value of \RELnew@apple. \RELnewmax is a \dimen variable which is only (effectively) active for the duration of an \item. \setbox\RELbox\hbox{\vtop to0pt{\let\\\cr \halign{##\hfil\cr#1\cr} \vss}}% Typeset the label in the horizonal box register \RELbox. The \halign (with \\ defined as \cr) allows multiple \\-separated lines in the label. \vtop to0pt and \vss make LaTeX think that this is a one-line box, regardless of the actual number of lines. \ifdim\wd\RELbox>\RELnewmax \RELnewmax\wd\RELbox\fi \expandafter\xdef\csname RELnew@\RELlabel\endcsname{\the\RELnewmax}% If the width of \RELbox is greater than the current maximum label width, increase \RELnewmax appropriately. Then, store the new maximum label width back into \RELnew@apple for use by the next \RELmakelabel. \hskip\labelsep \hskip-\relateright \hbox to\z@{\box\RELbox\hss}\hfill}% Print the left edge of the label at distance \relateright - \labelsep from the left edge of the text. \def\endrelate{\toks\z@\expandafter{\csname RELold@\RELlabel\endcsname}% \immediate\write\@auxout{\gdef\the\toks0{\csname RELnew@\RELlabel\endcsname}}% \endlist}% Finish the relate environment. \endrelate is called by \end{relate}. Write a line to the .aux file of the form \gdef \RELold@apple {28.74pt} as explained above. \makeatother \endinput That's all, folks! % 1987 Jun 10 E. Ledoux Creation % 1987 Jun 12 E. Ledoux Fixed problem with nested relate env's -------