[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Changes to FORMAT
- To: (BUG LISPM) at MIT-AI
- Subject: Changes to FORMAT
- From: GLS at MIT-AI (Guy L. Steele, Jr.)
- Date: Fri ,29 Feb 80 16:56:00 EDT
CC: GLS at MIT-AI, GSB at MIT-AI
I am done hacking FORMAT; I have tested it and it seems to work.
Naturally I'll fix any remaining bugs. A summary of changes:
I fixed a bug in ~C (it printed the in the wrong place).
The parts of ~C which need the names of special keys like
Return and Tab now use the same table which is used in the
reader to process #\. This table (an a-list) now resides
in the special variable SI:XR-SPECIAL-CHARACTER-NAMES.
(I updated LMIO;READ > for this purpose.) ~:C and ~:@C
perform a reverse look-up in this table, then capitalize the
name.
~@C is a fourth character print-out mode. It prints the character
in a READable format using #/ or #\ as appropriate (another reason
for using READ's #\ table). It deals with bucky bits too (e.g. #10/F).
~:* is like ~* but "exgnores" arguments, i.e. it backs up so that
you can reprocess them. ~n* backs up n arguments.
~:P is like ~P but does ~:* first. Hence (format nil "~D dog~:P" n).
~@P prints "y" or "ies" as appropriate. ~:@P does both. Hence
(format nil "~D pupp~:@P" n)
~nR means print a number in radix n. (I de-installed ~B, which I
had previously reported to mean Binary.) Thus ~8R = ~O. Any flags
or additional parameters are exactly as for ~D. The full form is
therefore ~radix,mincol,padchar,commacharR.
~@{ means use all the remaining arguments as the arguments to
be iterated over. ~:@{ means use all remaining arguments,
each a list to be used as a set of arguments, one per iteration step.
~^ means escape (mnemonic: throw UP (^)) from a loop. (Previously
I called this ~$, but renamed it because of a conflict with GSB's stuff.)
If there are no remaining arguments to process, terminate the enclosing ~{.
~n^ terminates iff n is zero; thus ~0^ is an unconditional termination.
~n,m^ terminates iff n=m. ~n,m,p^ terminates iff nmp.
If one is within a ~:{ (or ~:@{), however, then the set of arguments
one sees is for this iteration step only, and therefore ~^ terminates
only the current iteration step, allowing the commencement of the next one.
In this situation, ~:^ can be used to terminate the entire loop.
~^ used within a ~< terminates processing of ~< clauses. Only as many
as have been completely processed are used by ~<.
~^ outside of a ~{ or ~< terminates the processing of the entire FORMAT call.
If the first clause of a ~< is terminated by ~:; instead of ~;, then
the text resulting from the first clause (and the padding point
indicated by the ~:;) is not included in the justification process.
When the justification is done, then if the newly padded text will fit
on the current line (it always fits if you can't :READ-CURSORPOS the stream),
the justified text is output; but if it won't, the text from the first clause
is printed (it probably should contain a newline), and then the justified text.
If there is a parameter ~:n;, then the text must fit with n characters to spare
to avoid printing the first clause's text.
Incompatible change to ~{: it no longer automatically puts in ", "
between iteration steps. To do this one can use ~{text~^, ~}.
But with a little extra thought one can do even better than that.
For example, ~{~<~% ~:;text~>~^, ~} avoids splitting items across line
boundaries.
A numeric parameter n to any kind of ~{ limits the number of iterations to n.
The character # used as a parameter means the number of arguments left
to be processed. Like ~G and ~*, this is relative to any enclosing
iteration, or to the global FORMAT process if not so enclosed.
~@[text~] tests an argument. If nil, it swallows it and does nothing;
otherwise it does not swallow it and processes the text.
~[foo~;bar~;baz~:;quux~] does quux if one of the other clauses is not
selected; that is, ~:; indicates an "else" clause.
~[~1,2;foo~3;bar~4,5,17;baz~:;quux~] does foo if the argument is 1 or 2;
bar if 3; baz if 4, 5, or 17; and quux otherwise. This is a "tagged
cases" construct. If a tagged case has a :, then the tags are pairs
of range boundaries. Thus:
"~[~'+,'-,'*,'//;operator ~:'A,'Z,'a,'z;letter ~:'0,'9;digit ~:;other ~]"
A numeric parameter to ~[ uses that as the selector rather than using
an argument. This is mostly useful for ~#[.
~[, ~{, and ~< now all nest properly. Internally there is only one routine
which parses ~;-clauses, and only one routine which parses ~-commands (the
second uses the first).
I fixed up the reporting of errors in format strings. Control strings
are sometimes hard to decipher, so many errors now indicate the place
in the string where the error was encountered.