Article View: comp.text
Article #6382Troff Macro Programming A: Part 1 [repost]
From: Liam R. Quin
Date: Mon, 15 May 1989 18:50
Date: Mon, 15 May 1989 18:50
270 lines
8353 bytes
8353 bytes
This is the first in the promised series. There is also an introduction,
including both a PostScript and a text file (which I re-posted yesterday).
[Anduk's gateway fell over at the weekend sorry if this gets out twice]
============================================
Lightening Introduction to Troff Programming
Copyright (c) 1989 Liam R. Quin
I am including this article for those people who find the troff documentation
particularly difficult. In order to understand the rest of the material,
you'll have to be prepared to dive into your documentation, so this is
simply to help you get started. It is very terse.....
The examples all work, if you have the same version of troff that I do.
For what it's worth, I'm using ``SoftQuad Publishing Software'' Release 2.9.
I have marked with a side-bar where there are most likely to be
differences |
| old troff:
| Like this.
These are mostly to do with long variable names and error handling.
If you have an older release of sqtroff, see NOTE 1 near the end of this
article.
If you are likely to give courses in the future, see NOTE 2 at the en.
Lee
==============================
0. Lightening Overview
Troff has number registers, strings macros and diversions.
0.0 Number registers hold arbitrary *integer* expressions.
You can set them with
.nr register-name expression
where
register-name is a string of letters, numbers or punctuation
expression is a numeric expression.
Old versions of troff limit all names to 1 or 2 names.
You use them with
\nX 1-character name
\n(XX 2-character name
\n[xxx] 1, 2, or longer- character name
0.1 Strings hold a single word or phrase.
In other words, you can't put a newline into a string,
because it's the string terminator.
You set them with
.ds string-name "anything you like here
You use them with
\*[xxx]
(as for number registers. but with a * instead of an n).
0.2 macros hold multiple lines of unformatted (input) text.
You make a macro with
.de macro-name
text (which can include pretty much
anything)
..
where the dots have to be at the start of the line (but if I put them there,
old news and mail software will fall over!).
You use the macro with
.macro-name
in exactly the same way that you would use a normal request (.ps for example).
0.3 diversions hold formatted (output) text.
You make them with
.di diversion-name
text
.di
and use them with
.diversion-name
Typically when you use a diversion, you need to do
.in 0
.nf
.diversion-name
You will see why later.
Do not worry about the difference between macros and diversions at this
stage
[but I am not going to explain it in much detail on the net. See
TF:TR 5-14ff. if you have it, or look at your troff documentation.]
1.0 Interpolation
Troff reads its input (conceptually) a character at a time.
Strings and registers are ``interpolated'' as soon as they are seen
in the input.
| Old versions of troff:
In other words, if you do |
.ds Name "Simon | .ds Na "Simon
Hello, \*[Name], how are you? | Hello, \*(Na, how are you?
what troff actually sees is
Hello, Simon, how are you?
Similarly, if you do |
.nr Age 12+(300/12) | .nr A 12+(300/12)
Simon is \n[Age] years old. | Simon is \nA years old.
troff sees
Simon is 37 years old.
This means that you can use strings and number registers anywhere you like.
It also means that you sometimes have to take special pains to avoid troff
from `interpolating' things.
For example, if you want to print a backslash (\), you can't simply
include it in your text, because troff will look for a following * or n!
There are other things that you can put after a \, however, and one of
them is `e'. \e tells troff to print the current ``escape'' character;
this is normally the backslash.
The troff manual has a compete list of these things; this introduction is
to give you the general flavour of how things work.
[omitted: activity break involving creating a file containing strings,
registers and macros. You can go have a play if you want!! try making
a letter with the recipient's name in strings, perhaps, using a macro
for the address.]
1.3 Common problems:
* if you forget the
..
or the
.di
at the end of a macro or diversion, all of the rest of the input will
go into it, and of course won't be printed. Troff will give you an
error message:
sqtroff:filename:223:Diversion (diversion-name) not closed
or
sqtroff:filename:255:de:Macro definition not closed
including the filename and line number, sometimes or simply "(wrapup)" if
the error isn't detected until the end of all the input.
| old troff:
| there is no error message.
| The rest of your document
| will simply vanish.
* If you get the name of a string or register wrong, nothing will happen.
(sqtroff will give a warning if you have the warning level set
appropriately).
2.0 [awfully terse summary]
Remove a register with .rr
.rr regname [name2 ...]
remove a macro or string with
.rm name [name....]
Strings and macros share the same name-space. In other words, if you
do
.ds Name "Marion | .ds Na Marion
.de Name | .de Na
Here is My Name | Here is My Name
.. | ..
the .de first removes the string before defining a macro with the same
name. You do not get a warning.
Worse, if you do
.de de
you can no longer use the built-in `.de'! (But sqtroff will give a warning).
In order to define your own version of `de', you have to do
.rn de old-de \" rename the built-in request
.old-de de
whatever you want
..
Also, macro-aliasing does not notice that you | Old troff doesn't have
have redefined the request: | aliasing, so this does
.alias nr set-register | not affect you, except
.de nr | maybe to make you
. tm nr obsolete | jealous! :-)
.. |
then
.set-register
will continue to behave as .nr used to.
==============================
Good.
Summary:
number registers
expressions [see your manual, sorry]
strings
macros
diversions
Actions:
creating
removing
renaming
aliasing
Other Key Words:
name-space
interpolation
==================
NOTE 1 on sqtroff:
Some older versions used : instead of ., but only for lines involving
long names.
I suggest that you create a file called `tmac.acc', and put it in your
macro directory (probably /usr/lib/tmac). It contains:
:acc .
;ac2 '
.ev 1
:acc .
;ac2 '
.ev
.ev 2
:acc .
;ac2 '
.ev
with the leading spaces/tabs removed, and NO BLANK LINES.
Then do
sqtroff -macc other-arguments-to-troff
If you're still on 2.6 or older, you may have to put an explicit
.so /usr/lib/tmac/tmac.acc
(or wherever you put it) into each of your files. If you can't put
things in /usr/lib/tr\mac, you'll have to do that anyway).
The examples will then work for you.
====================
NOTE 2 on copyright:
Please ask me before charging people to learn troff from you with any of this
stuff. I will say almost certainly say yes, but I'd like to know if it's
being used! In any case, you should acknowledge that you got the material
from me.
Lee
End Of Part A
Part B
@ will start at ``Tricks With Names''
@ will show how to build stacks, arrays and so on.
@ will have an example set of macros to do bullet-lists (like
this one), which
1. nest (like this)
2. can use numbers (like this)
3. can use the special characters from part C, that are featured
in the PostScript example.
@ will be posted in a day or two.
--
Lee Russell Quin, Unixsys UK Ltd, The Genesis Centre, Birchwood,
Warrington, ENGLAND, WA3 7BH; Tel. +44 925 828181, Fax +44 925 827834
lee%anduk.uucp@ai.toronto.edu; {utzoo,uunet}!utai!anduk!lee
UK: uu.warwick.ac.uk!anduk.co.uk!lee
Technical Details
Message-ID:
<18@nx32s.anduk.co.uk>Path:
arc1-ca.pugleaf.net!utzoo!attcan!uunet!mcvax!ukc!warwick!anduk!leeShow Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!attcan!uunet!mcvax!ukc!warwick!anduk!lee From: lee@anduk.co.uk (Liam R. Quin) Newsgroups: comp.text Subject: Troff Macro Programming A: Part 1 [repost] Keywords: troff nroff SoftQuad Unixsys macro programming course Message-ID: <18@nx32s.anduk.co.uk> Date: 15 May 89 18:50:56 GMT Distribution: comp Organization: Unixsys (UK) Ltd, Warrington, England Lines: 270