budd@arizona.UUCP (07/22/83)
Thanks for the many cards and letters on my proposed revision for troff. I'm about to leave for vacation (Aug 4th, so you still have time to get in a flame or two), but before I did I thought I would give an example of what I am contemplating. Following this note I have attached (in shar format) three files. The first two are an example of input/output of a document illustrating some of my ideas of what troff macros should really look like. Scribe users will note the obvious influence of that system, which is in my opinion a fairly good model, as far as it goes (it doesn't have quite the versatility of troff, for example - no mathematics). The third file is the set of macros that were used to generate the second file from the first. Note that these macros will NOT work in normal troff, they are for the initial version of my new system. I am mostly interested in getting feedback on whether you think the new macros are easier to read/write/understand than those generated for troff. Before you have a chance to understanding them, however, some explanation must be given: 1. The 82 troff commands listed in the manual have been reduced to about 50 or so. This was largely done by removing commands that only set a register value (ps, ll, ls, etc) and replacing them with a .nr on the appropriate register. 2. There are several new commands associated with environments. Environments can be named, and you can have any number of them. The command "cv name" pushes a new environment on the environment stack, which is either uninitialized (no arg given) or initialized the same as the named environment (note this is a copy, the named environment is not changed). "ev name" is the same as cv, only any attributes not explicitly set are inherited from the previous environment. "pv name" pops the environment stack, and if an arg is given saves it under the given name. "rv name" clobbers the current environment on the stack, making it match the named environment. 3. Environments have 10 registers associated with them, named r0 to r9. These can be referenced, whether or not you are in the associated environment, by <env name-register name>. 4. Macros can be invoked in line during copy mode processing, using the format \*{name args}. There is a return statement for macros (.rt) and a while loop (.wy). The next major change will be to allow macros to have local variables. (Also on the todo stack- registers and strings are to be unified into one datatype - variable. This means number registers and strings will share a namespace, and will be evaluated the same way). 5. Tasks which i knew how to do, didn't need to do to get to the next problem, and which seem uninteresting i have left undone. Thus, for example, the symbol table still only allows two character names, although THIS WILL BE CHANGED as soon as i get around to it to allow arbitrary length names. Naming will be by \#a, \#(aa or \#{aaaaaa}. When this finally gets done several names in the macro package will be made somewhat more meaningful. So don't flame about the silly two character names - it's not an important issue. Also i have not installed the both margin justification algorithm, since this can just be copied from K&P, I had intended to do this but ran out of time, so the example is a bit silly in that regard. Thoughtful remarks and suggestions are solicited and welcomed. --tim budd {teklabs, ucbvax, kpno} | arizona | budd echo x - example cat >example <<'!Funky!Stuff!' .so macros .PP The next three paragraphs (actually the same paragraph repeated three times over) illustrate the effect of adjustments. The first is created using left adjustment, which is the default for the paragraph environment (this can be overridden, if desired). The second is justified on both margins, and is obtained by giving the "PP ad b" command. The third is right justified, which is somewhat odd but is nevertheless legal. The final is truly odd, being a paragraph which is both filled and centered. .PP ad b The next three paragraphs (actually the same paragraph repeated three times over) illustrate the effect of adjustments. The first is created using left adjustment, which is the default for the paragraph environment (this can be overridden, if desired). The second is justified on both margins, and is obtained by giving the "PP ad b" command. The third is right justified, which is somewhat odd but is nevertheless legal. The final is truly odd, being a paragraph which is both filled and centered. .PP ad r The next three paragraphs (actually the same paragraph repeated three times over) illustrate the effect of adjustments. The first is created using left adjustment, which is the default for the paragraph environment (this can be overridden, if desired). The second is justified on both margins, and is obtained by giving the "PP ad b" command. The third is right justified, which is somewhat odd but is nevertheless legal. The final is truly odd, being a paragraph which is both filled and centered. .PP ad c The next three paragraphs (actually the same paragraph repeated three times over) illustrate the effect of adjustments. The first is created using left adjustment, which is the default for the paragraph environment (this can be overridden, if desired). The second is justified on both margins, and is obtained by giving the "PP ad b" command. The third is right justified, which is somewhat odd but is nevertheless legal. The final is truly odd, being a paragraph which is both filled and centered. .PP in +10m sp 3v Other attributes can be similarly altered. For example this paragraph has been indented 10m. As you can see, it is further to the right than the others. Also, the amount of space between it and the last paragraph has been increased by modifying the sp attribute. .PP ll -10m ti 2m The line length can be changed by given the command "PP ll -10m", for example, which will produce lines shorter on the right. Also the amount of space the paragraph is initially indented has been reduced by using the "ti 2m" attribute specification. .MA PE ti 7m .PP You can make a permanent change to an environment attribute using the MA command. For example, we have just changed the default paragraph environment so that paragraphs are now indented by 7m. The command to do this was "MA PE ti 7m". .PP in +10m ll -10m Both the right and left margins can be indented by using the command form "PP in +10m ll -10m". This is the same as QS and QE in the ms macro package. .LP fi n An Unfilled paragraph is like a display. Here there are lines of different lengths, nevertheless it is not filled. .LP fi n ad r It can, however, be given an adjustment. Here an unfilled paragraph is right adjusted. A blank line normally starts a new paragraph, as was done here. This can be changed by giving the pg command. The pg command followed by a macro name establishes that macro as the macro to execute on blank lines. The pg command followed by no argument turn this feature off. There is a new form for command invocation. Besides the normal initial dot convention, a construct of the form \\*{name args} will evaluate the macro "name" in COPY MODE (ie, before the line is decoded). Macros can act as functions using the .rt command to return a value. There are a few built in commands for such actions as subscripting and character translation. There is also a new while loop (wy - perhaps it should be wyle loop). For a grand example of all of this see the roman number conversion routine in the macro package. For an example of its use, if you type \\*{RO 1983} you get \*{RO 1983}. There is also an upper case version \*{Ro 1983}. !Funky!Stuff! echo x - exam.out cat >exam.out <<'!Funky!Stuff!' 0 top of page 0 The next three paragraphs (actually the same paragraph repeated three times over) illustrate the effect of adjustments. The first is created using left adjustment, which is the default for the paragraph environment (this can be overridden, if desired). The second is justified on both margins, and is obtained by giving the "PP ad b" command. The third is right justified, which is somewhat odd but is nevertheless legal. The final is truly odd, being a paragraph which is both filled and centered. The next three paragraphs (actually the same paragraph repeated three times over) illustrate the effect of adjustments. The first is created using left adjustment, which is the default for the paragraph environment (this can be overridden, if desired). The second is justified on both margins, and is obtained by giving the "PP ad b" command. The third is right justified, which is somewhat odd but is nevertheless legal. The final is truly odd, being a paragraph which is both filled and centered. The next three paragraphs (actually the same paragraph repeated three times over) illustrate the effect of adjustments. The first is created using left adjustment, which is the default for the paragraph environment (this can be overridden, if desired). The second is justified on both margins, and is obtained by giving the "PP ad b" command. The third is right justified, which is somewhat odd but is nevertheless legal. The final is truly odd, being a paragraph which is both filled and centered. The next three paragraphs (actually the same paragraph repeated three times over) illustrate the effect of adjustments. The first is created using left adjustment, which is the default for the paragraph environment (this can be overridden, if desired). The second is justified on both margins, and is obtained by giving the "PP ad b" command. The third is right justified, which is somewhat odd but is nevertheless legal. The final is truly odd, being a paragraph which is both filled and centered. Other attributes can be similarly altered. For example this paragraph has been indented 10m. As you can see, it is further to the right than the others. Also, the amount of space between it and the last paragraph has been increased by modifying the sp attribute. The line length can be changed by given the command "PP ll -10m", for example, which will produce lines shorter on the right. Also the amount of space the paragraph is initially indented has been reduced by using the "ti 2m" attribute specification. ixcmzvldw bottom of page 0 1 top of page i You can make a permanent change to an environment attribute MA command. For example, we have just changed the default paragraph environment so that paragraphs are now indented by 7m. The command to do this was "MA PE ti 7m". Both the right and left margins can be indented by using the command form "PP in +10m ll -10m". This is the same as QS and QE in the ms macro package. An Unfilled paragraph is like a display. Here there are lines of different lengths, nevertheless it is not filled. It can, however, be given an adjustment. Here an unfilled paragraph is right adjusted. A blank line normally starts a new paragraph, as was done here. This can be changed by giving the pg command. The pg command followed by a macro name establishes that macro as the macro to execute on blank lines. The pg command followed by no argument turn this feature off. There is a new form for command invocation. Besides the normal initial dot convention, a construct of the form \*{name args} will evaluate the macro "name" in COPY MODE (ie, before the line is decoded). Macros can act as functions using the .rt command to return a value. There are a few built in commands for such actions as subscripting and character translation. There is also a new while loop (wy - perhaps it should be wyle loop). For a grand example of all of this see the roman number conversion routine in the macro package. For an example of its use, if you type \*{RO 1983} you get mcmlxxxiii. There is also an upper case version MCMLXXXIII. I bottom of page 1 !Funky!Stuff! echo x - macros cat >macros <<'!Funky!Stuff!' .nr sm 1 \" turn space mode on .nr pn 0 \" first page is numbered 0 .nr np 1 \" next page will be 1 .\"Top of Page Processing .cv TE \" first define top of page environment .nr ad 'l' .nr in 1i .nr ti 0 .nr r1 1c \" where top banner is going .nr r2 1i \" top of useful page .pv TE \" pop environment, capture attributes .\" .wh 0 TP \" at top of page, spring TP macro .\" .de TP \" TP - top of page macro ------------------ .ev TE \" first get into TP environment .nr sm 1 \" restore spacing .sp |\\#(r1u \" move to where banner goes .TL \\#(pn "top of page" \\*{RO \\#(pn} .sp |\\#(r2u \" move to top of user page .pv \" pop back out of top of tape environment .nr sm 0 \" turn no spacing mode on .. .\"Bottom of Page Processing .cv BE \" define bottom of page environment .nr ad 'l' .nr in 1i .nr ti 0 .nr r1 0-1i \" where the bottom of page trap goes (floats) .nr r2 \#(r1+2v \" where bottom banner goes .nr r3 0-1i \" whre the bottom goes (perm) .pv BE \" pop off and capture bottom environment .\" .wh \#<BE-r3> BP \" set up bottom of page trap .wh \#<BE-r3> FX \" set up footnote soaker (hidden unless needed) .\" .de BP \" BP - bottom of page trap .nr <BE-r1> 0+\\#<BE-r3> \" reset where bottom of page trap is .rm FY \" remove footnote overflow area .if \\#<FE-r2> \{ \" if there are footnotes .ev DE \" get in an appropriate environment .FB \" and dump them out .br .ie \\#(dl \{ .di \" footnotes overflowed, end diversion .nr <BE-r1> -\\#(dnu \" change footnote position .rn FY FB \" remove footnote body .\} .el \{ .rm FB \" else remove body .nr <FE-r2> 0 \" no footnotes now .\} .nr sm 1 \" insure space mode is on .sp |\\#<BE-r3> \" go to top of normal BP, springing FX .sp 1u \" just a bit more, make sure fx is spung .pv \" restore environment .\} .ev BE \" get in bottom of page environment .nr sm 1 \" insure space mode is on .sp |\\#(r2u \" go to where banner goes .TL \\*{Ro \\#(pn} "bottom of page" \\#(pn .br .pv \" go back to previous environment .ch BP \\#<BE-r1> \" reset bottom of page footnote trap 'bp \" now break page, without line break .. .de FX \" soak up excess footnotes .if \\#<FE-r2> \{ .ev \" ev allows bar to get in before text .di FY \" start up new diversion .br ------- .br .pv \" pop back to old ev to get rest of text .\} .. .\"Footnote management .cv FE \" define footnote environment .nr in 0 .nr ti 0 .nr r1 1v \" amount to space on footnotes .nr r2 0 \" number of footnotes on current page .pv FE .\" .cv DE \" DE - display environment, .nr fi 'n' \" can be used to display diversions .nr ls 1 \" since it takes the text .nr ad 'l' \" verbatim, no change .pv DE .\" .de FS \" FS - footnote start .ne 4 \" need enough space for reference and 1 line .nr <FE-r2> +1 \" add 1 to footnote counter .ev FE \" get into the right environment .AT \\$* \" modifying attributes if user wants .da FB \" divert into footnote body .ie 1=\\#(r2 \{ -------------- .br \} .el .sp \\#(r1u .. .de FE \" FE - footnote end .br \" break any pending text .di \" end diversion .pv \" restore previous environment .nr <BE-r1> -\\#(dnu \" change location of bottom page trap .ch BP \\#<BE-r1> \" change bottom of page trap .if ((\\#(pl+\\#<BE-r1>) < \\#(cx ) .BP \" too big, spring trap now .. .\"Three part titles .de TL .ev .nr ls 0 .nr fi 'n' .nr ad 'l' \\$1 .br .nr ad 'c' \\$2 .br .nr ad 'r' \\$3 .br .pv 'sp 1v .. .\"Environment Attribute Setting .de NS \" see if a spefic attribute was specified .nr xx 2 .nr xy 1 .wy \\#(xx < \\#(.$ \{ .if '\\$1'\\$\\#(xx' .nr xy 0 .nr xx +1 .\} .rt \\#(xy .. .de AT \" set attributes .nr xx 1 .wy \\#(xx < \\#(.$ \{ .ds x1 \\$\\#(xx .nr xx +1 .ds x2 \\$\\#(xx .nr xx +1 .SA \\*(x1 \\*(x2 .\} .. .de SA \" single set attribute processor .if '\\$1'ls' .nr ls \\$2 .if '\\$1'll' .nr ll \\$2 .if '\\$1'ps' .nr ps \\$2 .if '\\$1'vs' .nr vs \\$2 .if '\\$1'in' .nr in \\$2 .if '\\$1'ti' .nr ti \\$2 .if '\\$1'sp' .nr is \\$2 .if '\\$1'ad' .nr ad '\\$2' .if '\\$1'fi' .nr fi '\\$2' .. .de MA \" MA - modify environment .cv \\$1 .AT \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9 .pv \\$1 .. .\"Paragraffitti .ev PE \" push a new environment for text .nr ls 1v .nr fi 'f' .nr ad 'l' .nr ti +5m .nr is 40u .pv PE .\" .pg PP \" a blank line gets a new paragraph .\" .de PP \" PP - standard paragraph start .br \" break any pending text .rv PE \" reset attributes .AT \\$* \" change any attributes user specified .sp \\#(isu \" issue initial space .nr ti +\\#(in \" take whatever ti was given and add indent .nr sm 0 \" turn on no space mode .. .de LP .br .rv PE .nr ti 0 \" same as pp with no initial ti .AT \\$* .sp \\#(isu .nr ti +\\#(in \" but perhaps the user gave one .nr sm 0 .. .\"Register Instructions .de EV \" EV - Evaluate an arbitrary expression .nr xx \\$1 .rt \\#(xx .. .de r+ \" r+ register post increment (for in line use) .nr xx \\#{\\$1} .ie ''\\$2' .nr \\$1 +1 .el .nr \\$1 +\\$2 .rt \\#(xx .. .de r- \" r- register post decrement (for in line use) .nr xx \\#{\\$1} .ie ''\\$2' .nr \\$1 -1 .el .nr \\$1 -\\$2 .rt \\#(xx .. .de +r \" +r register pre increment .ie ''\\$2' .nr \\$1 +1 .el .nr \\$1 +\\$2 .rt \\#{\\$1} .. .de -r \" -r register pre decrement .ie ''\\$2' .nr \\$1 -1 .el .nr \\$1 -\\$2 .rt \\#{\\$1} .. .\"Roman Number Conversion .de RO \" RO - roman number algorithm .ie 0=\\$1 .ds zz 0 .el .ds zz \\*{R1 \\$1 ixcmz vldw} .rt \\*(zz .. .de R1 \" roman number algorithm - internals .ds xx .if \\$1 \{ .ev .ds xx \\*{R1 \\*{EV \\$1/10} \\*{ss \\$2 1 10} \\*{ss \\$3 1 10}} .nr r1 \\$1 % 10 .nr r2 \\#(r1 / 5 .nr r3 \\#(r1 % 5 .ie 4=\\#(r3 \{ .as xx \\*{ss \\$2 0 1} .ie 1=\\#(r2 .as xx \\*{ss \\$2 1 1} .el .as xx \\*{ss \\$3 0 1} .\} .el \{ .if \\#(r2 .as xx \\*{ss \\$3 0 1} .wy \\*{r- r3}>0 .as xx \\*{ss \\$2 0 1} .\} .pv .\} .rt \\*(xx .. .de Ro \" Ro - upper case roman number .rt \\*{tr \\*{RO \\$1} ixcmzvldw0 IXCMZVLDW0} .. !Funky!Stuff!