Macros and Programming
The macro facility is divided into two levels, referred to as Macros and Programming. The difference is formal: the two levels involve different commands, which cannot be combined on a single line of a macro (though they can be combined within a single macro), and the Programming Dialect requires the presence of a special interpreter file. In addition, you can record a macro by asking Nisus to watch what you are doing, and then go in afterwards and customize the macro that Nisus has created for you.
The Macro level, in a nutshell, allows you to do anything you could have done with menus and typing. You can enter find-and-replace commands in a single line rather than having to make Nisus fill in the Find dialog piece by piece, and a few other menu commands can similarly be encoded in condensed form within a macro; but the net effect is precisely to automate actions you could have taken through menus and keyboard. A macro can call itself or another macro; the find-and-replace syntax provides a means of terminating a macro, which may be in a loop or calling itself, if the find fails. The macro file appears in a window which is a version of the regular text window, with the normal tools at the top of the window and all menus available; this means you can include rulers and styles in a macro and cause them to appear in the document on which it operates. Writing macros is not at all difficult (although I find I have to have the manual in front of me if I’m to remember the find/replace syntax), and there is an excellent facility for testing them: you can tell Nisus to regard any selected text as a macro and to attempt to execute it (and you can Undo the results in one stroke, so you’re not afraid to experiment).
What the Programming dialect adds is: mathematical and string operations and functions; a rudimentary control structure (if, goto, exit); functions for obtaining information about the document – what is the name of the ruler governing the current insertion point? what is the character offset (from the start of the document) of the insertion point? of the current ruler? of the next ruler?; a storage class which is sort of a cross between an array and a stack; and commands for obtaining or setting the selection point in the document. A thing you are likely to do is combine the selection-point commands with the storage class. For example, you might do a find which results in a number of non-contiguous selections; you could then store the selection-points in the storage class; this would allow you to run through the selections one by one, doing some complicated (possibly conditional) operation on each of them.
The power of all this is so obvious as to need no further elaboration. Yet, to the reader’s possible astonishment, I should like to say that I think nowhere near enough power is provided. Nisus has a lot to live up to in this regard. On my little Apple ][c, with just 128K, I ran a program called Gutenberg. This fantastic program, by John Wagner of Scarborough, Ontario, is my measuring stick for all other word processing programs. It had no WYSIWYG bells and whistles, of course; but it revolved around a programmable page-layout language with which you could dictate, through a nesting series of macros, down to the last pixel what your dot-matrix printer would ultimately generate (in other words it was like TeX). What attracts me to Nisus is that it dwells in Gutenberg’s philosophical world; what disappoints me is that it never quite lives up to its promise. That’s right: I’m saying that Gutenberg was more powerful.
The reason for this is that Gutenberg’s programming language gave the user access to something Nisus’s does not: the global variables of the document. There is no way to find out from within a Nisus macro such things as: what is the font of the text at the insertion point? what, numerically, is the placement of the left margin? what, numerically, is the position of the insertion point on the line? (You can figure out how many characters there are from the start of the line to the insertion point, but not how many centimetres.) Similarly, you cannot set these global variables, unless through a menu command – and menu commands do not do everything. There is absolutely no way, from within a Nisus macro, to set a tab or move a margin. (Of course you can impose a ruler which includes preset tabs and margins; but I’m talking about being able to respond flexibly and numerically to the actual situation: e.g., set the left margin to 1 inch more than its present value.) I cannot believe that it would be much trouble to add this sort of facility and give Nisus’s programming language some truly incredible power. Remember, this is all stuff I used to be able to do on an Apple ][. Paragon does realize this, but has had other priorities, such as getting Nisus Compact and Nisus XS out the door. I’d like to see them focus on their programming language next, since it would help Nisus to further break from the word-processor pack.
One silly feature of macros, by the way, is that for many commands you need to be able to enter special symbols for Option, Shift, Command, arrow-keys, and the like; a special font is provided to allow this, but there is no way to type some of the symbols (no way to type any of them if you’ve no Control-key) – you have to pull down a special window called ASCII which shows the symbols, and double-click each one as needed to get it into the macro. (However, things are better than they used to be. In Nisus 3.01, you couldn’t even see the symbols in the ASCII window; you had to memorize their ASCII codes, and double-click the correct code number to cause the required symbol to appear in your macro!) The only other workaround is to turn on macro recording, type some keys with the modifiers down, and then copy the modifier symbols from the recorded macro. It’s clumsy, but it works. I just leave the symbols in a comment at the top of my macro file so they’re easy to get to.