From Gene.Rollins@PROOF.ERGO.CS.CMU.EDU Tue May 17 22:15:15 1988
>From Gene.Rollins Mon May 16 16: 40:41 1988
To: peter.lee@PROOF.ERGO.CS.CMU.EDU, fp@PROOF.ERGO.CS.CMU.EDU
Subject: TeXing programs
Date: Mon, 16 May 88 16:40:18 EDT
From: Gene.Rollins@PROOF.ERGO.CS.CMU.EDU
Resent-To: shivers@h
Resent-Date: Tue, 17 May 88 16:06:36 EDT
Resent-From: Peter.Lee@PROOF.ERGO.CS.CMU.EDU


>from netnews via Bill Scherlis....

Date:     Thu, 28 Apr 88 06:15 PST
From: <ASND%TRIUMFCL.BITNET@forsythe.stanford.edu>
Subject:  Pretty Printing with TeX

Norman Ramsey's requirements for a pretty-printing package
intrigued me, and spurred me to write such a beast.  It has
not been exhaustively tested yet though. The macros are given
below, and here are the instructions:

To turn on pretty printing, use \prettyprint, most usefully
inside a group or a \vbox.  Don't set new values for \hsize,
\parindent, \indentation, \indentincrem or \availwd inside
the pretty-printing environment.  Do set \indentation and
\indentincrem to appropriate values BEFORE \prettyprint,
usually at the beginning of a document.

Program structures are grouped within square brackets; a
structure can be complex, with many clauses and sub-structures,
or as simple as a single statement.  Clauses within a structure
are either a) separated by \clause (or \lastclause) or b)
enclosed by [ ].  Pretty-print will put all of a structure on
one line unless a) it doesn't fit or b) it contains a sub-structure;
either a) or b) will cause the structure to be printed with each
clause on a separate line, with the second and ff. indented
one step futhter.  \clause before [ is redundant but does not hurt.
No \clause is assumed after ], which is in fact just an end group
character like }.

Each structure at the outermost level is typeset as a paragraph,
so try not to enclose a whole program in [ ] or the paragraph may get
too big.  At the outermost level, the brackets are not necessary for
short, simple lines. \obeylines is in effect so there are linebreaks
between statements.

Of course the names of the macros can be changed, and the definitions
customized to a particular (programming) language.  For example, in C,
one could make { and } do the work of [ and ], with echoing, and use
some other characters for ordinary TeX grouping.

%%.......................Macros........................

% Pretty-printing program listings;
%           by Donald Arseneau
\newif\ifononeline     % should this structure try to fit on one line?
\newdimen\indentation  % total indentation (set to initial value before using)
\newdimen\indentincrem % increment for each level of nesting
\newdimen\availwd      % width available to a sub-structure
\newbox\structure      % one structure of the program (contents of [])

%   turn on program listing style (should probably be in a group)
\def\prettyprint{%
    \parindent=\indentation % initial indentation
    \availwd=\hsize
    \advance\availwd by-\indentation\advance\availwd by-\indentincrem
    \advance\availwd by-\rightskip \advance\availwd by-\leftskip
    \ononelinetrue
    \catcode`[=\active
    \catcode`]=2 % closing
    \obeylines}  % obeylines only affects outermost level

%   the [ character
\def\startgrouping{\global\ononelinefalse  % all super-structures multiline
    \ononelinetrue  % This structure tries to be one line
    \newpar         % start a new line, and indent
    \afterassignment\startstructure  % do \startstructure in the hbox
    \setbox\structure=\hbox\bgroup}  % box this structure

\def\newpar{\par\noindent\hskip\indentation\relax} % at outer level, use par

%    first thing in hbox
\def\startstructure{%
     \let\newpar=\clause % nested structures are \clause s, not \par s
     \aftergroup\endstructure  % after the hbox, end structure
     \advance\indentation by \indentincrem % increase indentation for clauses
     \advance\availwd by -\indentincrem
}

%    first thing after hbox
\def\endstructure{%  decide how to output structure,
                  %  on one line (\box) or multiline (\unhbox):
     \let\next=\unhbox
     \ifononeline \ifdim\wd\structure<\availwd
           \let\next=\box
     \fi\fi
     \next\structure
     }

%    set the breakpoint between clauses.
\def\clause{\ifdim\lastskip=\indentation \else % \clause\clause acts as one
     \hfil\penalty-200  \hskip-\indentation\relax
     \null\nobreak\hskip\indentation\relax
     \fi}
%    a clause that should not be indented as far as others
%    e.g., ...\lastclause ENDIF]
%    (could instead use simply:  ...]\clause ENDIF )
\def\lastclause{\clause
     \hskip -\indentincrem}

\catcode`[=\active \let[=\startgrouping \catcode`[=12

%............... Now to test ..............
\let \\=\clause
\begingroup
\indentation=1in  \indentincrem=1.5em
\hsize= 3in  %%%%  try different values:  fails below 2.8in
\prettyprint

% don't need [ ] at outer level, and \obeylines is in effect
program test
variables are nonsense
[$a:=3$;]
% use [ ] to delimit clauses forces separate lines:
[if $a=3$ [then $b:=2$;] [else $b:=0$;];]
% use \clause (alias \\) to delimit clauses:
[for all $i$: \\ $at:=at+v(i)$;;]
[for all $j$:
%  note no obeylines inside a structure
  [if $v(j)>1$ \\then $v(j):=1/v(j);$ \\[else if $v(j)<0$
    \\then $v(j):=v(j)~2$; \\else $v(j)=\sqrt{v(j)}$;];]
\\$bt:=bt+v(j)$;]
exit
[end]

\endgroup
\bye
                              Donald Arseneau
                              asnd@triumfcl.bitnet
                              userasnd@mtsg.ubc.ca



