341 Chapter 12. Automating Nisus Writer
In this chapter, youll learn
In this chapter, were going to discuss the most powerful and exciting aspects of Nisus Writerits automation features. Well start with a look at glossaries, which can save you tons of effort by storing often-used text and graphic elements. But the real power of automation comes from macros, which well cover in much greater detail. Because macros require a lot more thought than most Nisus Writer features 342 (and have a much steeper learning curve), were going to switch gears a bit when we get to the Macros section and take more of a tutorial approach. Try working through all the examples yourself, and the text will make a lot more sense.
When youre typing, chances are, many of the same words and phrases crop up a lotthings like your name, phone number, E-mail address, or Sincerely, John Smith. Or perhaps theres a certain equation you use a lot, or bibliographic entries that get used for every paper you write. With Nisus Writers glossaries, you can enter things like that using just a couple of keystrokes, rather than re-creating them each time.
A glossary is a special file Nisus Writer uses to store text, graphics, and other document elements along with abbreviations for each. The concept is simple: put the text (or graphic or whatever) in your glossary once, and give it a short, easy-to-remember abbreviation. When you want to insert that element into a document again, you can either choose the abbreviation from a menu or just type in the abbreviation, followed by a keyboard shortcut that expands it to its full form. In writing this book, for example, I used abbreviations like nw for Nisus Writer and pfp for PowerFind Pro to save quite a bit of typing and keep spelling errors to a minimum.
Creating and Expanding Abbreviations
Heres how you do it. First, make sure youre on the text layer and select the text, graphic, or whatever you want to store. Choose New Abbreviation
from the Glossary submenu of the Tools menu. The Glossary Entry dialog box (Figure 12.1) will appear, asking you to type in an abbreviation. Type in a short abbreviation (note that case is significant), and click OK. Youll then see your entry in the glossary editing window (Figure 12.2), where you can edit if you wish. When youre satisfied with the way your entry looks, close the glossary editing win-343dow. Your new abbreviation will appear on the Glossary submenu, and you can insert the glossary entry into your document by choosing that menu command. Or type in the abbreviation, then choose Expand Abbreviation from the Glossary submenu or press the keyboard shortcut Command-\.

Figure 12.1. The Glossary Entry dialog box.

Figure 12.2. The glossary editing window.
|
|
Abbreviations will only be expanded if they are typed into your document as whole words. That is, if you have the abbreviation ee associated with the glossary entry Electrical Engineering and select the word tree before choosing Expand Abbreviation, nothing will happen. |
The Expand Abbreviation command (and its associated keyboard shortcut) can work in either of two ways. First, if you have no text selected and there is an abbreviation immediately to the left of the insertion point (no spaces in between), the abbreviation will be expanded. Or, if you select any range of text that includes one or more abbreviations as separate words before choosing Expand Abbreviation, all the abbreviations within the selection will be expanded to their full glossary entries. This means that, if you wish, you can simply type abbreviations without interrupting yourself as you create a document, then at the end choose Select All and Expand Abbreviation to expand all the abbreviations in your document at once.
|
|
The Expand Abbreviation command works not only in your document window, but also in the macro editing window, the glossary editing window itself, and even the Find/Replace dialog box. |
The glossary editing window appears whenever you choose New Abbreviation
, so that you can examine your glossary entry and make any desired changes to it before continuing. If you want to edit your glossary entries or abbreviations later, choose Edit Glossary File
from the Glossary submenu to display the glossary editing window. This window looks and acts like other Nisus Writer windowsyou still have access to all of your formatting controls, though not to the Sound Bar or Graphics Bar. The most obvious difference is the split-pane layout of the window: the abbreviations are listed on the left, and the actual glossary entries on the right. You cant edit an abbreviation directly, but double-clicking on an abbreviation will open a dialog box allowing you to rename it. You can, however, edit freely in the right side of the window. Glossary entries are separated by gaps that look like page breaks in your document window.
The abbreviations in this window are attached to the return character at the end of the preceding glossary entry (just like rulers in your document are). So if you want to copy a glossary entry (to duplicate it and make changes, or copy it to another glossary file, for example) and include its abbreviation, be sure to select that previous return character before copying, cutting, or dragging and dropping. When you close the glossary editing window, all your glossary entries will appear in alphabetical order on Glossary submenu of the Tools menu.
Your glossary entries are stored in a special Nisus Writer document called a glossary file. You can have as many different glossary files as you like (each with an unlimited number of entries), but only one can be open at a time. To open another glossary file, locate it using the Open dialog box or Catalog, and click Open. If there are glossary files you use frequently and would like to be able to switch to easily, you can add them to your Essential Files list.
345 Normally, changes to your current glossary file are not saved until you quit Nisus Writer. To save the file manually, just choose Save while the glossary editing window is the active window. If you have just added entries to your glossary for the first time, your glossary file will be named Nisus Glossary File and stored in the same folder as your Nisus Writer application. This file will then be opened automatically whenever you launch Nisus Writer. To change the default glossary file, simply move your current one from the Nisus Writer folder, move a new one into its place, and name the new file Nisus Glossary. To create a brand-new, empty glossary file, choose New Glossary File
from the Glossary submenu.
What Can You Put in a Glossary?
You can put anything in a glossary that you can put on the text layer of a documentnot just text, but character graphics (including tables and equations), movies, sounds, page graphics, variables, and autonumbers. You can even include PowerFind or PowerFind Pro expressions, and anything in your glossary can have styles or markers applied to it. There is also no limitation on lengthglossary entries can run several pages or more if you wish. There is a minor limitation, though. While the text in your glossary entries can contain footnotes, headers/footers, graphics, or sound, you cant create any of these elements from within the glossary editing window. So if you need to include those elements in a glossary entry, type them into your document first, then select them and choose New Abbreviation
.
|
The enclosed CD-ROM contains several new ready-made glossary files, which contain abbreviations for common phrases, various types of tables and equations, Find/Replace expressions, and more. |
Styles and Rulers in Glossary Entries
When youre in the glossary editing window, you can apply fonts, sizes, and styles to your text just like you would anywhere else. When you insert a styled glossary entry into your document, it will retain whatever attributes it had in the glossary. However, you can also make your text pick up the attributes of the surrounding text where it is inserted, if you 346 wish. To do that, select your glossary entry in the glossary editing window, and choose Any Font, Any Size, +Any Styles, and/or Any Color from their respective menus. Glossary entries styled with one of the Any attributes will pick up the characteristics of that attribute (font, size, style, or color) from the surrounding text when it is inserted.
You can also name rulers and define new styles in the glossary editing window. If you define a style in the glossary editing window and then insert a glossary entry that uses this style into your document, the new style name will be transferred into your document too and added to your Style menu. Similarly, if you name a ruler in the glossary editing window and then insert a glossary entry which includes that ruler into your document, the ruler name will be transferred along with the paragraph(s) to which it applies. However, a ruler will not be copied into your document if it is the first thing in your glossary entry. This is because the ruler is attached to the return character at the end of the previous entry, and is not considered part of the current entry. On the other hand, if you have a paragraph as your glossary entry that uses a defined style with an attached (named) ruler, inserting that paragraph into your document will bring the ruler with it.
While glossaries can save you lots of typing, they can only hold static items. You can use a glossary entry to insert an object into your document, but not to make changes to your document or perform any other activities. The next level of automation in Nisus Writer is macros, which will allow you to create a shortcut for nearly any imaginable activity. Macros are Nisus Writers most powerful, yet least understood feature. In the remainder of this chapter, Ill try to make sense of macros and help you to unlock this power for your own use.
So what is a macro anyway? Quite simply, its a single command that can activate any number of other commands in a 347 sequence. Its a way of doing in a single step what would ordinarily take several. To take a trivial example, lets suppose you regularly open a new file, paste in the contents of the clipboard, and then save the file. You could create a very simple macro that does those three steps for you with a single menu command, and thereby save a bit of effort. But macros can go far beyond this humble example. They can perform calculations, manipulate text, ask for input, and so onin other words, they can do much more than just repeat sequences of activities youd normally do by hand. Macros are stored in special Nisus Writer documents called macro files. A single macro file can contain any number of separate macros. The macros in the currently open macro file, along with commands for recording and editing macros, are found on the Macros submenu of the Tools menu (Figure 12.3).

Figure 12.3. The Macros submenu of the Tools menu. Macros in the currently installed macro file are listed at the bottom.
Well, our macro adventure has to start somewhere, so lets jump in and get started. Ill show you around briefly to get you oriented, then well sit down and talk details. Well start by recording, editing, and playing a simple macro. Then well discuss the capabilities of macros in general before delving into the more sophisticated macro commands.
The easiest way of creating a macro in Nisus Writer is using the Record command. I often refer to this as the watch-me mode, because thats exactly what it does: Nisus Writer watches what you do, and records each action you perform. When you stop recording, you can give a name to the sequence of activities you just did, and this name will then appear on the Macros submenu. Any time you want to repeat those same activities, just choose that name from the menu.
Lets walk through the exact procedure of recording a basic macro step-by-step. You can then apply this technique to your own activities.
Record from the Macros submenu of the Tools menu. While you are in Record mode, the Tools menu name will blink on and off.
New from the File menu.
Macros are FUN! and press return.
Select All from the Edit menu.
Bold from the Style menu.
FUN and then choose Underline from the Style menu.
Stop Recording from the Macros submenu of the Tools menu.
Test and click Name.
What you just did was record a macro that will create a new file, type some text in it, apply the style Bold to it, and underline one word. In other words, all the steps you just performed manually have now been recorded. You can vary steps 2 through 6 (and add as many additional steps as you like) to make your macro perform different functions.
Now that youve recorded your first macro, lets play it back. Before doing so, you may close the new document you just created (if you wish)no need to save changes. Now go to the Macros submenu of the Tools menu, and youll see a new menu choiceTest (the command you just added). When you choose Test, your macro will run, repeating all the steps you recordedbut a lot faster than you could have performed those steps manually.
Nisus Writers Undo command works on macros, too. In fact, if you have just run a macro and then choose Undo, Nisus Writer will undo the entire macro (except for opening, closing and saving files, which cannot be undone anywhere in Nisus Writer). If you want to stop a macro before it finishes running, press and hold the Command and period (.) keys. The macro will pause and a dialog box will ask you if you want to stop the macro or continue to the end. To cancel the macro, click Stop, or to let the macro complete its activities, click Continue.
Youll recall that when we finished recording our sample macro, we gave it a name and then saw the macro editing window. The reason this window opens automatically when youre finished recording a macro is so that you can edit, or fine-tune, your macros. We chose not to do that with the macro we recorded, but you can go back at any time and change your macros. Lets do that now. Choose Edit Macro File
from the Macros submenu, and youll see the macro 350 editing window, which looks something like Figure 12.4 (yours may be slightly different). Youll notice that the macro you recorded consists mainly of menu commands, and you can probably tell just by looking at it what each line does. Nevertheless, lets walk through it line by line.

Figure 12.4. The macro editing window, showing the Test macro.
New
Key Macros are FUN!
Key means that whatever comes after it is typed in, just as though you had pressed those keys on the keyboard. Note that there is a space between the word Key and the text you typed in.
Key
Space, Tab, & ¶ turned off) a space. The word Key on a line all by itself doesnt mean anything, but Key followed by a space means type a returnwhich, youll recall, we did immediately after typing in Macros are FUN!
Select All
Bold
Click 86, 76
Click 86, 76
Underline
As you can see, theres nothing complicated about this macro. It simply lists all the things you did, one activity per line. If you want to change it or add to it later on, just type in new commands. For example, if we decided that we wanted our text to be italic instead of bold, all wed need to do is highlight the word Bold, and type in Italic instead. To delete a command from your macro, just delete the line that lists that command. To change a macros name, double-click on the macros name on the left side of the macro editing window. A dialog box will appear, giving you a text box to enter the new name in. Type in the name of your choice, and click OK.
Congratulationsyouve done it. You have successfully recorded and edited a macro. While there are many, many more things you can do with macros, you will always be following roughly the same procedure. And if you can type in the commands you see on menus, plus words like Key and Click, then you can easily create macros from scratchoften without any recording at all. Were ready to move on to bigger and better things but first, lets review exactly what Nisus Writers macros can do.
352 Macro Capabilities and Limitations
Before we go any further, you should know a few things about what macros can and cannot do. Well discuss the pros and cons of individual commands as we go along, but there are a few general features Id like to mention up front. Keep in mind that the limitations I mention here need not be troublesomeanything can be worked around with a little creativity.
What Macros Do and Do Not Record
When you are using Nisus Writers watch-me recording mode, your mouse clicks and menu selections are automatically recorded in the macro file. However, for the most part, the recording is blind. For example, if you close a window by clicking the close box, what will be recorded is the mouse coordinates where the click occurred. If you close a window by pressing Command-W, that keystroke will be saved. The only way the Close command itself will be recorded is if you choose the command from a menu. However, at least when you click the mouse, the coordinates are recorded relative to the nearest corner of the active window where you first clicked. This means that, for example, clicking the close box or the zoom box can be performed by a macro even if the window is moved or resized. Unfortunately, floating tool bars are not seen as windows, meaning that if you record a click on a tool bar button and the tool bar moves, your macro will not work correctly, as Nisus Writer will try to click at the location on the screen where the button was when the macro was recorded.
Only individual mouse clicks are recorded. Clicking and dragging is not recorded, which means you cant record resizing graphics or selecting text with the mouse. However, you can still select text in a macro using keyboard shortcuts (see Appendix A), and you can record resizing graphics using the Scale
command. Choices from pop-up menus (like the Ruler Name menu) are not recorded. However, you can type a ruler name directly into a macro to select that ruler. Some pop-up menus, though, like the Mail Services 353 pop-up in the Recipients area of the PowerTalk mailer, are invisible to the macro engine and cannot be accessed from a macro.
Nearly all keystrokes are recorded, including combinations that involve holding down the Command, Shift, and/or Option keys while typing something else, as well as the arrow keys. However, the Control key is not recorded, and if you have an extended keyboard, the Function Keys, Help, Page Up, Page Down, Home, and End keys will not be recorded.
Macros are not limited to just what you can record. You can also type in a macro by hand, and in so doing, include a lot of commands and functions that arent on any menu. For example, you can do many kinds of mathematical and trigonometric calculations, and you can have any number of variables in your macro, representing numbers, text, or both. You also have access to special storage units called arrays, which let you refer to many different values with a single name. Special commands like If() and Goto let you branch to different parts of your macro (or other macros) depending on various conditions that you specify. You can ask the user for input, and you also have complete control over your clipboards, rulers, styles, selections (even noncontiguous ones), display attributes, and more. Well explore all of these capabilities below.
For the most part, macros only run when you choose the macro name from the Macros submenu of the Tools menu (or press a keyboard shortcut youve assigned to one of them). Macros are not designed to run continuously in the background while you do other editing tasks in Nisus Writer. However, it is possible to activate macros automatically when certain activities are performed. Several macro names (see Table 12.1) are treated specially such that when any macro has that name, it will execute automatically when the event indicated occurs.
|
354 Macro Name |
Runs automatically when you |
option |
option-double-click a word |
command |
command-double-click a word (note: command-double-clicking performs the |
CommandOption |
command-option-double-click a word |
InitInit |
open the macro file (runs when you launch Nisus Writer if this macro is in your Nisus Macros file) |
InitOpen |
open a (non-stationery) file |
InitNew |
open a new file, a stationery file, or import a (nongraphic) file |
SwitchIn |
switch to Nisus Writer from another application |
InitRevert |
choose |
Table 12.1. Macros with these names run automatically under the conditions stated.
I should point out that just as macros cannot run in the background within Nisus Writer, they also cant run while Nisus Writer itself is in the background and another application is active.
|
|
If you want to prevent the InitInit macro from running when a macro file is opened, hold down the Command key while you open the file (or launch Nisus Writer). |
OK, now that youve got your feet wet and know what Nisus Writer macros are all about, youre ready for the major leagues. You are now enrolled in Joes Macro Writing School. Instead of presenting the entire macro system in a big chunk, Ive broken down macro writing into ten fairly short lessons. If you walk through these step by step, youll learn how to perform all the major macro functions and get all the background you need to write complex macros yourself.
A lot of people are put off by the idea of writing macros because it seems too much like programming (not some-355thing ordinary mortals should be able to comprehend). Well, I have a secret to tell you. I am not a programmer. Really. I probably could, if it came right down to it, program my way out of the proverbial paper bagafter all, I did have an entire semester of BASIC in high school. But thats it. Howeverand this is a big howeverI am a geek, and this means that I like to experiment with my computer. I am also lazy, which means I want to avoid extra work whenever possible. These two sterling qualities are, it turns out, just what it takes to perform incredible feats of electronic legerdemain with Nisus Writers macros. And in fact, if you can write an outline for a paper, get your kids ready for school, or play checkers, you too have all the skills you need. Well walk through everything here step by step, and in no time youll be automating your work like you never dreamed you could. Fair enough?
Were going to look methodically at the steps involved in creating and debugging macros. We will not cover every single command in detail (though they are all listed in Appendix C for your reference), but instead look at a small number of the macro commands very thoroughly. As I looked through all the macro files I have, I discovered two amazing things. First, there were dozens of commands that were never used at all. Second, there were a few very simple commands (especially Find/Replace) that were used over and over in a staggering number of macros. In fact, the vast majority of my most useful macros involved only simple commands, and nothing like programming at all. So well concentrate on the most useful and important commands, and leave the other details in Appendix C for your own exploration later.
Lesson 1: Organizational Details
Welcome to class. Sit anywhere you want, but please, no chewing gum. Our first lesson will get you acquainted with the macro writing environment, the conventions used, and some shortcuts to make your macro writing easier.
When you finish recording a macro, the macro editing window (see Figure 12.5) opens automatically, allowing you to review your macro and make any desired changes. You can also open this window manually to edit existing macros or to add new macros from scratch without recording. To open the macro editing window, choose Edit Macro File
from the Macros submenu of the Tools menu. If you want to add a new macro to your file without recording, choose New Macro Command
from the Macros menu. A dialog box will appear asking you to name the new macro, and the macro editing window will open (if its not already open), showing a new, blank macro at the bottom of the window with the name youve just entered.

Figure 12.5. The macro editing window.
The macro editing window is very similar to other Nisus Writer windows. You still have access to the Text Bar, and most of the familiar commands on the menus (Tools, Insert, Font, Size, Style, etc.) are still available. You can use the Spelling Checker, the Thesaurus, and Find/Replace within the macro editing window. There are some things you cant do in this window, like access the Graphics Bar or the 357 Sound Bar, insert headers, footers or footnotes, or print. But for the most part, you can use all the same editing tools youre used to using. Like the glossary editing window, the macro editing window lists the macro names on the left and the macro text on the right. There is a gap between macros that looks like a page break in the document editing window. If you double-click one of the names on the left, the Macro Name dialog box will pop up, allowing you to rename or delete the macro. Like entries in the glossary window, the macro name is attached to the last return character in the preceding macro. So if you want to copy a macro, including its name (either to duplicate it in the current macro file or to paste it into another one), be sure to select the previous return character as well (see Figure 12.6). Since the first macro has no return character preceding it, you cannot copy its name along with the macro text.

Figure 12.6. If you want to copy an entire macro, including its name, select the preceding macro last return character, as shown here.
|
|
To print out the text of your macro(s), you must first copy it into a regular Nisus Writer document. However, macro text in the special Any Font font will take on the characteristics of the surrounding text where it was pasted. To display and print your macros in the Any Font font, place an opening chevron («, entered by typing Option-\) at the beginning of the macro and a closing chevron (», or Shift-Option-\) at the end. Then select the chevrons and everything between them. You will now be able to choose Any Font from the Font menu, and your macro text will look the same way it did in the macro editing window. |
Macros are, generally speaking, insensitive to font, size, and style. A macro written in Zapf Chancery will work just the same as one written in Geneva. By default, the macro editing window uses the Any Font font (which looks like Chicago), because it contains special symbols for keys like Shift, Option, Command, and Deletebut you may use any character attributes you wish. The only times font, size, and style are relevant in your macros are in Find/Replace expressions and when using the Paste command (both of which will be discussed in more detail below).
Every new macro you create will be listed by name on the Macros submenu of the Tools menu. However, new macros will not show up on this menu until you close the macro editing window. Macros are listed alphabetically on the menu and in the macro editing window. Sometimes, however, when you add a new macro (which appears initially at the bottom of the window) and save the macro file before closing the window, it gets stuck there. The remedy is to open the macro editing window and close it without saving, then open it again. If that doesnt work (and occasionally it doesnt), double-click the name of the misplaced macro to display the Macro Name dialog box, then just click Name without making any changes. Close the macro editing window, and it should jump to the right position.
|
|
358 To rearrange the order in which your macros appear, change their names so that their alphabetical order changes. To move a macro to the top of the menu, add a space at the beginning of its name. To move it to the bottom, try a tilde (~). By using other special characters like bullets (, option-8), you can group macros together without needing very much naming creativity. Note that except for the space character, any special characters at the beginning of a macro name must be included in the name when you call the macro from another macro. |
As mentioned earlier, macros are stored in macro files. All the macros in the currently open macro file (only one can be open at a time) are shown in the Macros submenu. If you make changes to the macro file, they are not saved along with your document, but when you quit Nisus Writer or try to open another macro file, a dialog box will appear asking if you want to save the changes. To save changes to the macro file manually without opening a new file, choose Save from the File menu while the macro editing window is in the foreground.
When you first install Nisus Writer, there is no default macro file. If you record or create new macros and then choose Save from the File menu (or click Save when asked if you want to save the file when you quit), the macros will be stored in a file called Nisus Macros. This file will be placed in the same folder as your Nisus Writer application.
You can open a different macro file at any time using the Open command or the Catalog. If you want to explicitly create a new macro file, instead of adding macros to the current file, choose New Macro File
from the Macros submenu. The new macro file will contain a single, empty macro (called <Untitled macro>), and you can then record, type in, or paste in additional macros of your choice. Macro files, like any other Nisus Writer document, can be placed on your Essential Files list for quick access.
|
|
While working in the macro editing window, you still have access to unlimited undos, and as always, they remember the window in which a command was performed. However, as soon as you close the macro editing window, you lose the ability to undo anything you did there (even though the file itself is still open). If you do seriously munge your macro file and then close it, you can recover the previously saved version using Revert to Saved. |
If you do more than casual editing of macros from time to time, youll soon discover that its a real drag (pun intended) to display the Macros submenu of the Tools menu every time you want to use a macro command. Fortunately, theres a great shortcut to display that menu. Just hold down the Option key while clicking anywhere on the title bar of your document (or any other window except the glossary window or clipboard window), and the Macros menu will pop down (see Figure 12.7). Better still, if you want to edit (rather than run) a particular macro, press either Shift or Command (along with Option) as you choose a macro from the menu. The macro editing window will be opened right where the text for that particular macro starts.

Figure 12.7. The Macros menu, displayed by pressing Option while clicking on the title bar.
One of the first things any good programmer will tell younot that Id know from personal experience, mind youis that you should add liberal comments to your code (geekspeak for program; in our terms, the code is the series of instructions that makes up your macro). Comments are remarks that dont affect the function of the macro in any way, but just give you reminders of whats going on. In a macro, any time you have two slashes (//) in your text, the rest of that paragraph is considered a comment and not part of the macro itself. This means that you need not put your comments on a line by themselves (though thats how its usually done). You can put as many comments in your macro as you like without affecting its performance.
|
While most of the sample macros in this book dont contain comments (since theyre explained in the text), the macros on the CD-ROM do. Take a look at some of those to get an idea of what constitutes thorough commenting. |
Why use comments? Two reasons. First, they serve as a reminder to you of why you did things the way you didso you dont have to figure them out again later. Second, if you are writing macros that somebody else will be using, your comments will help them to understand the reasoning you used. While macros (including comments) can be in any font or style, its a good idea to use a different font and size for comments (Geneva 9 is my personal preference) so that you dont confuse them with the rest of the macro.
You should also know about the odd command on the Macro menu called Execute Selection. This command will be your close friend (so close that you will definitely want to assign an easy keyboard shortcut to it, like Command-E-S). It lets you test a macro, or part of it, without leaving the macro editing windowjust highlight your macro text and choose Execute Selection. The macro editing window will move to the back, and your macro will be immediately performed in the window that was immediately behind it. Whats especially nice about Execute Selection is that you can use it on just a small portion of your macro, if you want to test a certain command without running the whole thing. (If your macro contains any variable definitions (see below) that are used in the selection, be sure to select those definitions.) Execute Selection even works on noncontiguous selections!
The Execute Selection command will work anywhere in Nisus Writernot just in the macro editing window. You can actually type a command right into your document window (or, for that matter, even in the Find/Replace dialog box or in a clipboard window!) and run it like a macro by selecting it and choosing this command. The thing to keep 361 in mind is that this command always runs the macro in the next window back, not in the current window (unless you only have one window open). So if your macro involves manipulating any text, be sure the text in question is in the window immediately behind the current one, or that first line of the selection is the name of the window in which you want the macro to run.
As we saw earlier, you can put any Nisus Writer menu command on a line by itself and it will be executed as though the command had been chosen with the mouse. This is one of the easiest things you can do with a macro, yet some very complex macros can be constructed by doing no more than typing in a series of menu commands. Now, you may be wondering which commands you can use for this. In fact, people have written to Nisus asking for a list of all the menu commands that can be used this way. The simplest answer is, All of them. Thats rightany command on any menu in Nisus Writer can be used in a macro. If you want a list, all you need to do is pull down your menus and look. In addition to your regular menus, you can use named rulers in your Ruler Name menu, clipboards on the Clipboard menu, and items on the Display Attributes menu. But thats not all. Even commands on menus that you can modify yourself can be used. These menus are File Access (Essential/Last Used Files), Jump To, Glossary, Macros, Windows, defined styles on the Style menu and the Apple menu (main level only). The only exceptions are the Application menu, the Keyboard menu, and the Guide menu.
|
|
While its true that any command on any menu can be activated from a macro, you should remember that just as in manual operation, not all menu choice are available all the time. For instance, the Cut command is dimmed when nothing is selected, and the commands on the Graphics menu only make sense when the graphics layer is active. These same restrictions apply to macros. If you try to activate a menu command at an inappropriate time, Nisus Writer will just beep at you. |
When you type in a menu command, be careful to use exactly the same spelling that appears on the menu (including spaces, if any). However, you dont need to worry about casetyping bOLd will have exactly the same effect as typing Bold. You also dont need to worry about typing the ellipsis (
) that comes after some commands, like Print
. There may be cases, though, in which exactly the same command appears on two different menus. For example, there may be a window named Letter and a glossary entry or macro thats also named Letter. If this happens, you need to 362 specify which command you mean. The way to do this is to type the name of the menu first, then a colon, then the menu command (no spaces), as in Insert:Table or Macros:Update. In this last example, Macros:Update, notice that the Macros menu doesnt appear on your main menu bar; its a submenu of the Tools menu. However, as far as macros are concerned, a submenu is just another menu.
As you know, many of Nisus Writers menus can be changed by pressing one or more modifier keys. Modified menu commands can also be used in macros, but with a little more effort. To use a modified menu command, you need to type in the command as it usually appears (without modifier keys), and precede it with the special symbol(s) from the Any Font font representing the modifier key(s) you want to use (see Figure 12.8 for some examples).

Figure 12.8. A macro showing the use of modified menu items. Note that you cannot simply type the command as it appears on the menu when it is modified.
There are several ways to get the modifier keys into your macros:
Command, Option, and Shift are only recorded when choosing a modified menu command or when pressing another key at the same time.)
|
It goes without sayingbut Ill say it anywaythat Ive included these special symbols in both the macro and glossary files on the CD-ROM. |
While any menu command can be entered on a line by itself, some menu commands can optionally include additional information to specify how they are to be applied or what extra work they are to do. Lets take a simple example. You want your macro to create a new file named Report. How would you do this? Well, youd undoubtedly begin with the command New, which will (depending on how your preferences are set) open a new, untitled document. But then youd have to give the document a name. To do this, youd need to enter Save As, type in the name Report using the Key command described later on in this lesson, and then click the Change Name, Dont Save button, either using its keyboard shortcut (Command-R), or by recording the mouse clicking the button. Thats a lot of steps for a very small result. Luckily, theres an easier way. Instead of just typing New, type New "Report" and your new file will automatically be named Report. The word "Report" after the word New is known as an argumentit is a modifier which supplies additional information to the menu command.
Using arguments with menu commands can save you a lot of extra steps, as youve seen, and it can also allow you to perform some fancy tricks with certain menu commands. The commands that take optional arguments are: New, Open, Show Catalog, Save As, Quit, Cut, Copy, Paste, Find/Replace (along with some variations that well discuss in Lesson 3), Jump, and Mark. Many of these commands can take two separate arguments, and some of them can also be used with modifier keys to produce even more combinations. Because there are so many variations on these commands, I wont give an example of each one herebut if you take a 364 look at Appendix C youll find a complete list of all the possibilities. Instead, let me give you a few interesting examples here to try out, and ask you to look in the appendix for additional options.
|
|
You must use straight quotes, not smart quotes, to enclose arguments. If you have Smart Quotes turned on, you can type a straight quote by pressing the Command key while you type the quote character. |
New. Weve already seen how you can create a new file with a particular name using the command New "Filename". You can actually go one better: create a new file with a particular name and specify where it is to be stored on disk. To do this, enter New "Pathname:Filename" (for example, New "Macintosh HD:Documents:Price List"). See Appendix C for additional argument types that let you create a new folder or base your new file on a stationery document.
|
|
Pathnames will come up again. A (full) pathname starts with the name of your hard drive (or whatever volume the file is on), followed by a colon (:), then the name of the folder the files in, another colon, and the name of the file itself. For files nested several folders deep, just include each folder name in order before the name of the file. |
Open. The Open command is very similar to New, except that you always specify the exact pathname to an existing file. The format is Open "Pathname:Filename". Appendix C will also indicate how to open a particular folder in the Catalog, and add or remove files from the Search List.
Save As. Enter Save As "Pathname:Filename" to save your current document (in regular Nisus Writer format) in the specified location.
Cut. The Cut command all by itself deletes text and places it on the current clipboard. To cut text to a particular clipboard, type Cut "x", where x is replaced with the number of a clipboardfor example, Cut "7" to cut the text and place it on clipboard 7.
Copy. As with Cut, you can specify which clipboard to copy something to, using Copy "x", where x is the number of a clipboard. However, you can add another argument to place some specific text on the clipboard (without it needing to be selected in your document). For instance, Copy "3" "Ice Cream" will place the words Ice Cream onto clipboard 3. To copy text onto the current clipboard (without specifying a number), just leave out the number between the first set of quotes: Copy "" "Ice Cream".
Paste. Like Cut, Paste can refer to any clipboard, and can take an additional argument saying what text is to be pasted. So Paste "2" will paste the contents of clipboard 2 at the insertion point, and Paste "" "Harvey" will paste the name Harvey at the insertion point. But what would happen if you typed Paste "2" "Harvey"? Two things: Harvey would be pasted in, and if anything was already selected, that item would first be copied onto clipboard 2. In other words, its a sort of swap paste.
Find/Replace. Well talk about this in the next lesson, but as a preview, you can give the Find/Replace command up to four arguments: (1) what to find; (2) what to replace it with; (3) what search options to use; and (4) which window to search in. The command Find/Replace "wheat" "rice" "aW" will replace all occurrences of the word wheat with the word rice.
Jump. Use Jump "Marker Name" to jump to a bookmark youve assigned. See Appendix C for the formats to use to jump to a line or page number, to select text between markers, and to remove marker names.
Mark. If you have text selected, you can use Mark "Marker Name" to mark the text with the name specified. For example, Mark "Quartz" assigns the bookmark name Quartz to the currently selected text.
There are a few menu commands (notably Cut, Copy, Paste, and Find/Replace) that, as we have seen, can take as an argument any amount of text. There may come a time when, in addition to (or instead of) text, youd like to use a ruler as an argument for one of these commands. As you know, rulers are attached to return characters, so any time you use a ruler in one of these commands, a return character must be included too. Ill show you how to do this with Paste; the rest function the same way. Take a look at Figure 12.9. Youll see on the first line is the Paste command, followed by two double quotes (to indicate that were not going to do a 366 swap paste), then an opening quote and a backslash. The backslash within an argument tells it that the return character that follows should not be taken as the end of the command but should be interpreted literally. This return character, then, is the one to which we must attach the ruler. This is done by going to the next line, choosing Paragraph Ruler from the Insert menu, and applying the desired attributes to the new ruler. Finally, the closing quote (on the line with the ruler) completes the argument. When this command is executed, a single return character with the ruler attributes we just set will be pasted into the document.

Figure 12.9. Using a ruler in an argument of the Paste command.
|
|
The margin settings for your macro editing window may be different from that of your document, and unfortunately, the macro windows margins cannot be changed. So all ruler settings are taken to be relative to the left margin, rather than absolute. |
|
|
While the procedure just mentioned will certainly get a ruler into your document, depending on what youre trying to accomplish, there may be an easier way. The menu command Paragraph Ruler in a macro will insert a blank paragraph ruler (plus a return unless youre at the beginning of a line). Or, if the ruler you want to use is named, you can simply use the ruler name as a menu command to apply that ruler. |
Turning Menu Commands On or Off
You may wish to do something in a macro like making sure the Info Bar is showing. At first, this might seem easy; just type the Info Bar command on a line by itself. But this assumes the Info Bar is not currently visible. What if it is? This command will then turn it off, which is not what we wanted to do. Sometimes you need to be sure that something is specifically on or off at certain time, regardless of its previous condition. For such occasions, youll be delighted to know that some menu commands can take as an argument either "on" or "off" (as in Info Bar "on"). This is true of any menu command which can be toggled on and off in your document by choosing it and re-choosing it; commands in the on mode have a checkmark next to them on their menu. Examples of commands that can be on or off are Info Bar, Space, Tab & ¶, Headers/Footers, and any style. (The command Show Clipboard can also take an "on" or "off" argument, even though it does not toggle on or off using the menu command.) Here are some sample lines from a macro that show the usage of the "on" and "off" arguments:
367
Info Bar "off" Sound Bar "on" Show Clipboard "on" Italic "off"
You can get menu commands into Nisus Writer macros either by recording what you do or by typing. In most of these lessons, I assume youll be typing in your commands, because it allows you to see (and correct) what youre doing as you enter the macro, and because it gives you a lot more flexibility than recording your macros. However, there are still times when even an advanced user will want to record, rather than type, a macroor at least record a few steps, which can then be pasted into another macro. In general, use recording when:
Macros can simulate the effect of typing using the command Key, as we saw earlier when we recorded our first sample macro. To use Key, type it at the beginning of a line, then type a space, then type in the actual text youd like to be entered. No quote marks are needed, unless you want the quote marks themselves to be typed. The space is, however, obligatory. To simulate pressing the return key (which works both in your document window and in dialog boxes where this has the effect of clicking a button), type Key followed by a space and press Return to make that the entire contents of the line. To simulate typing the tab key, enter Key followed by a space and a tab.
The Key command can also type the modifier keys Command, Option, and Shift (but not Control); the arrow keys; and the Delete (or Backspace) key. It can even type 368 combinations of these keys, like Command-P, Shift-Option-J, or Option-Up Arrow. This means that, among other things, you can use a macro to activate a keyboard shortcut youve defined in lieu of entering the command itself. The modifier keys are represented in your macro editing window by special symbols that are part of the Any Font font. They always appear after the word Key but before the characters they modify (if any). To get the special symbols into your macro, you can use any of the techniques described above under Menu Commands with Arguments.
Examples of the use of Key are shown in Figure 12.10. Try typing this in, exactly as written, to test the various permutations of the commandthen experiment with your own variations.

Figure 12.10. Examples of the use of Key in a macro.
|
|
You can record keystrokes that activate multi-key keyboard shortcuts, like Command-C-A-T for Show Catalog. But be careful when using several keyboard shortcuts in a row, because when playing these back, Nisus Writer does not pause between them. So if you have a multi-key shortcut defined that is the same as two or three individual shortcuts in a row, the macro will always play back as though you were pressing the longer sequence. |
Lesson 3: Find/Replace in Macros
Without question, the most frequently used macro command is Find/Replace. Why? Two main reasons. First, its very easy to useafter all, you already know how to use PowerFind and PowerFind Pro; this is just more of the same thing. Second, its very powerful. Virtually any kind of document reformatting can be done using nothing more than a series of Find/Replace commands. You already know this, toomacros simply give you a way to automate the searches further. Because of this, our next lesson in Macro Writing School 369 is how to use Find/Replace in macros. If you learn nothing elsebranching, variables, stacks, or whateverlearn this.
|
|
One of the most highly praised new features in Nisus Writer was instigated by yours truly: a button in the Find/Replace dialog box called Macroize. It takes whatever (Normal, PowerFind, or PowerFind Pro) expression is currently in the Find/Replace dialog box, along with any options on the Find/Replace menu, and creates the appropriate line of a macro for you automatically. So if all the syntax and options youre about to read about still strike you as a little obscure, save yourself the effort and just click the button! |
As we saw in the last lesson, Find/Replace is one of the menu commands that can take arguments. In this case, there will usually be three arguments: what youre looking for, what you want to replace it with, and what the Find/Replace options are. Lets look at a basic example:
Find/Replace "these" "those" "aA"
This reads, Find the word these and replace it with the word those using the options a (Replace All) and A (Whole File). (Well return to discuss the available options shortly.) If its helpful for you in reading and constructing Find/Replace commands, you can actually put words between the arguments like so:
Find/Replace "these" with "those" using "aA"
Anything between the arguments is ignored by the macro, but it can make it clearer to you what each argument is for.
You are not limited to using literal text in your Find/Replace macro commandsyou can also use PowerFind or PowerFind Pro expressions. This means that you can do anything the Find/Replace dialog box can do from within a macro, without actually having to display the window, type in Find and Replace expressions, and click buttons. To enter a PowerFind expression into a macro, you must first build it out of metacharacters in your Find/Replace dialog box as usual, then copy and paste it into the macro. The metacharacters must still go between quotes, and in addition, you need to use the option e, which means this is a PowerFind expression (PowerFind was originally called EasyGREP, which accounts for the e). Other options may be added as needed. Figure 12.11 shows the way a PowerFind expression will look in the macro editing window.
370

Figure 12.11. A macro command containing a PowerFind expression.
|
|
You can apply fonts, sizes, and styles to parts of your Find and Replace expressions in the macro editing window just as you can in the Find/Replace dialog box. |
Most often, though, youll probably want to use PowerFind Pro expressions in the macro window, since they dont require any copying and pasting, and are a lot more flexible than PowerFind. (Also all the examples in this book and on the CD-ROM use PowerFind Pro!) To tell the macro that what youve entered should be interpreted as PowerFind Pro metacharacters and not as literal text, youll use the option g (for grep). Figure 12.12 shows the same command we just looked at, this time as a PowerFind Pro expression.

Figure 12.12. A macro command containing a PowerFind Pro expression.
Since you wont be displaying the Find/Replace dialog box or the Find/Replace menu, you need some way of telling your macro which Find/Replace options to use in a given searchlike Ignore Case, Whole File, and so on. Each of these options is represented by a single character (see list below), and when this character is included in the options argument, the corresponding option will be used for that particular search. The list of options you supply may be short or long, depending on the specificity you need, and options can be listed in any order. Weve already seen the e option meaning PowerFind and the g option meaning PowerFind Pro. A full list of options is found in Appendix B, but Table 12.2 gives you a basic list to get you started.
|
371 Option |
Argument Character |
|
Ignore Case |
i |
|
Dont Ignore Case |
-i |
|
Whole Word |
w |
|
Not Whole Word |
-w |
|
Whole File |
A |
|
Dont Wrap Around |
-A |
|
Search All Open Documents |
G |
|
Search Front Window Only |
-G |
|
PowerFind |
e |
|
PowerFind Pro |
g |
|
Literal Text |
|
|
Find Text Only |
o |
|
Replace Text Only |
O |
|
Replace All |
a |
|
Terse (dont display a dialog box telling how |
t |
|
Terminate (exit the macro if nothing is found) |
T |
|
Use options as set in Find/Replace dialog box |
|
Table 12.2. A partial list of options for Find/Replace commands in macros.
The default options Nisus Writer assumes are -e (literal text), -G (front document only), i (Ignore Case), o and O (Find and Replace text only), t (terse), -w (not Whole Word), and A (Whole File). In other words, if you want to use any of these options, you dont need to list them explicitly. You only need to list the options that differ from the defaults (though in this book, just to make things clearer, Ill frequently list more than is required). Any options you set will be used for that command only, and then the defaults will apply again.
Here are a few sample Find/Replace commands, with a variety of options, along with explanations so you can see whats happening.
Find/Replace "\r\r+" "\r" "gaAt"g (PowerFind Pro), a (Replace All), A (Whole File), and t (terse).
Find/Replace "\(
\)\(:d+\)" "\2\1" "ga-AG"g (PowerFind Pro), a (Replace All), -A (Dont Wrap Around), and G (Search All Open Documents). Since the -A option is used, the search will only go from the current insertion point to the end of each open document.
Find/Replace "him" "her" "wA-i"w (Whole Word), A (Whole File), and -i (Dont Ignore Case). Because the a option is not used, this will replace only the next occurrence of him in the file, not all of them.
Find/Replace "^:b+" "" "ga"g (PowerFind Pro) and a (Replace All). This will also use the settings A (Whole File) and t (terse) even though theyre not listed, because those are among the default settings.
While all the above examples used three arguments, you can also use the Find/Replace command with two arguments or four arguments. If you have only two arguments (as in Find/Replace "this" "that"), the first one is assumed to be the Find expression and the second one, the Replace expression. Since there is no options argument, the default options are used. If you have four arguments (as in Find/Replace "this" "that" "gaAt" "Letter"), the fourth argument is taken to be a window name. Use this argument to restrict your search to a particular window.
Variations on the Find/Replace Command
If you have been experimenting with the Find/Replace command in macros, you may have discovered that there doesnt seem to be any way of performing a Find All or a Find Next 373 without replacing anything. There is a way of doing it, but it does not involve changing the options argumentit involves changing the Find/Replace command itself. Recall from Chapter 11 that by pressing various modifier keys, the Find/Replace command on the Tools menu can be changed to Find Next, Find All, and several other options. It so happens that you can use any of these commands in a macro as well, in place of the Find/Replace command. For example, the command Find All "the" will find and noncontiguously select all instances of the word the in your document; Find Next "the" will find and select just the next instance.
|
|
The variations on the Find/Replace command that can be used in macros are an exception to the usual way of entering modified menu commands. With most modified menu commands, you would have to enter the special symbol for the Shift, Option, and/or Command key followed by the command name that appears on the menu when no modifier keys are pressed. With these commands, however, no special symbols are needed. |
The commands that can be used in this fashion are: Find Next, Find All, Find in Selection, Replace With, Replace All, and Replace in Selection. The commands Find Next, Find All, Find in Selection, and Replace With can take one, two, or three arguments. If there is just one argument, it is taken to be the Find (or Replace) expression. If there are two arguments, the second one is the Find/Replace options to be used, as listed above (default options are used if none are specified). And if there are three arguments, the third one is taken to be a window name. The commands Replace All and Replace in Selection require both a Find argument and a Replace argument, with optional options and windows arguments. Here are some examples of modified Find/Replace commands:
Find All "\^:u:a+" "g" finds and selects all capitalized words at the beginning of a line.
Find in Selection ":d+" "g" finds and selects all sequences of one or more digits within the current selection.
Replace With "sugar" "" "Report" will replace each currently selected block of text in the window named Report with the word sugar.
Replace All "sugar" "cream" replaces all occurrences of sugar with cream; equivalent to Find/Replace "sugar" "cream" "aA".
Replace in Selection "in" "out" "w" replaces all occurrences of in with out, but only within the current selection, and only if in is a whole word (the w option).
374 Recess Story: A Tale of Two Dialects
At this point I need to mention something that it pains me to say. I was hoping to avoid this subject altogether, but I couldnt find a way. O.K. (deep breath)the Nisus Macro Language (yes, it is a language) is actually composed of two mutually exclusive dialects. Unlike other programming or scripting languages, there are two distinct varieties of commands you can use in writing Nisus Writer macros, and if you mix them in the wrong way, your macros wont work. Now, I hasten to add that for many people, this distinction will make no difference at all (as well see). But it is important to be aware of it and to keep it in mind when writing macros.
The Menu Command Dialect consists ofyou guessed itmenu commands (with or without arguments). Any command on any menu in Nisus Writer can be typed on a line by itself in a macro; the set of all these menu commands constitutes the Menu Command Dialect. In other words, its what weve talked about so far. This dialect also includes a few special items that dont actually appear on a menu. First is the word Key, which as we saw earlier, is used to type literal text (including return characters) and keyboard shortcut sequences. Next is the command :1, which as you will see below is used to display a dialog box, optionally with user input. Third are the Clipboard commands (also discussed below), \CC and \C0 through \C9. And the commands click (to simulate a mouse click) and beep (to play the system alert sound) are also part of the Menu Command Dialect. Every other command is part of the Programming Dialect.
So what difference does it make that there are two dialects? Well, the significance is that you cant have commands from both dialects on the same line. Ever. Now, in most cases, youll only have one command per line anyway, so this wont matter. But sometimes you need to combine commands, and this is where the problem arises. Fortunately, there is always another way to accomplish the same task. For example (Programming Dialect commands are underlined):
|
375 Bad (mixing dialects) |
Good (not mixing) |
| If(count>5)Copy | If(count>5) MacroCopy |
| :1 "The number is:" 'myVar * 2' | clipboard = myVar * 2 :1 "The number is:" '\CC' |
| Copy; x = x + 1 | Copy x = x + 1 |
If you can keep in mind while you write macros that mixing dialects is a no-no, youll be in great shape. And if you ever get confused as to which dialect somethings in, consult Appendix C for a complete reference. Having said all of that, were going to turn our attention primarily to Programming Dialect commands in the next lesson and the ones that follow.
If your mathematical background includes at least a junior-high algebra class, you know what a variable isa letter that can stand for any number. The exact value of the variable at any given time depends on the context, but the great thing about variables is that you can use a single pattern to represent a lot of specific cases. In Nisus Writer macros, too, variables are quite handy, because they allow you to make general statements that will apply to a lot of specific cases. They also let you perform calculations, count, and much more.
Variables in macros go beyond the xs and ys you used in algebra. For one thing, variable names are not limited to just one letterthey can include many letters, uppercase or lowercase (or even numbers). So the word count could be a variable name, and so could Joe7. Also, variables can store not just numbers but also strings of alphabetic characters, the time or date, or a true/false value. Lets take a look at whats involved in using variables in macros.
For starters, every variable has to have a name. You can name a variable pretty much anything you want, but its a good idea to give it a name that you can remember easily, and that has some relevance to what it represents (so TicketCount and Input are good variable names, w34_A7ls and xyz are not so good). There are just a few rules you need to be aware of:
dave and Dave could be two different variables.
qpush, error, length, etc.). However, you may use the name of a menu command as a variableHelvetica, Thesaurus, and Save are just fine.
In Nisus Writer there are five different kinds of variables, corresponding to the five data types the macro language can work withlong integers, double-precision floating-point numbers, strings, date/time, and Boolean (true/false) data. Any given variable name can only have one type in a particular macro. Lets look more carefully at each type.
The reason we need to be so picky about what type of variable we have is that only certain operations can be performed on certain kinds of variables. For example, you can take the square root of a number, but not of a letter. So any time you use a variable, you have to be aware of what its type is, and what operations are and are not permissible for that type.
So how do you give a variable a name, determine its type, and give it a value? Very easilyin fact, its all done in a single step. This step can be referred to as defining a variable, declaring a variable, or instantiating a variable. In some programming languagesso Ive heardyou cant use a variable until you have named it and assigned it a particular 378 type. In Nisus Writer, variables automatically figure out what their type is based on the value theyre assigned when they are first used. This all-in-one process of naming, getting a data type, and getting a value, is known as autoinstantiation. Lets look at some examples of how this works:
Val = 32 defines a new variable named Val with a type long (since 32 is an integerno decimal point), and gives it the value 32.
Sal = 2.8 defines a new variable named Sal with a type double (since 2.8 is a floating-point number), and gives it the value 2.8.
Hal = "Mississippi" defines a new variable named Hal with a type string (since what comes after the = sign is in quotes), and gives it the value Mississippi. Anything in quotes will be treated as a string, even if its a string of numbers.
Pal = date defines a new variable named Pal with a type date/time (since the word date is a special predefined variable that always has as its value the current date), and gives it the value of todays date.
Cal = 4>3 defines a new variable named Cal with a type Boolean (since whats on the right of the = sign is an expression that can be true or false), and gives it the value true.
Variables can change their values repeatedly, but they will keep their type throughout the duration of the macro, unless explicitly cleared using a command like free (see Appendix C for details).
|
|
Your first use of a variable in a macro must give it some specific value, so that it can figure out what type its supposed to be. A statement like count = count + 1 would not be O.K. as an instantiating statement, because count cant tell what its starting value should be. |
When a macro ends, any variables that were used in that macro are erased. So the next time you run a macro, you start with a clean slate. Any variables you want to use must be defined again, and whatever values a variable had before are forgotten. A variable whose value is remembered only in 379 the current macro is said to have local scope. And unless you specify otherwise, all variables will be locally scoped automatically. If one macro calls another, any local variables that were used in the first macro retain their value in the second macro. The macro values are only cleared when the original macrowhere the variable was definedends.
But there may be times when you want a variable to remember its value even after the macro that defined it has stopped. You can give a macro global scope, so that it will retain its value until you quit Nisus Writer, and any macro that runs after the variable is initially defined can access the global variable without having to redefine it. To make a variable global, just add an extra line before its definition with the command global followed by the variable name:
global CupOfSoup CupOfSoup = "Cream of Chicken"
Theres actually quite a bit more that could be said about local and global scope. And there are a number of commands that let you override the default behaviors of both types of variables, clear them at any time, and so on. While its important to know how long variables retain their memory, you wont need to worry further about global and local commands unless you are writing pretty complex macros. But never fearAppendix C contains a complete list of macro commands that you can refer to when the time comes.
When you have a numeric variable (either long or double), you can use it in calculations, variable assignments, and so forth as though it were a number. The most important symbol you need to know about when working with numeric variables (or any variable, for that matter) is the equal sign (=). This means is being assigned the valuefor instance, abc = 37 says the value 37 is hereby assigned to the variable abc. You can also use = in conjunction with mathematical operatorsfor example cde = 8 + 5 sets cde equal to 13. You can even use parenthesesnested to any levelin calculations, and you dont need to worry about 380 preceding them with backslashes as you do in PowerFind Pro. So if you run this macro:
value = (2 + (5 * 3) / 5 - (4 - 2)) * 3 clipboard = value :1 '\CC'
it will give you a result of 9, which is just what youd expect. Notice that I have added spaces around all the mathematical operators to make the expression more readable, but the spaces are not requiredspaces are ignored in numeric calculations.
You may need to assign the value of one type of variable to a variable of another type. For example, lets say you have a double variable called pi whose value is 3.1415926, and you assign this value to a variable of type long called pizza, using the command pizza = pi. When a double value is assigned to a long variable, everything past the decimal point is truncatedno rounding occurs. So in this example, pizza would be equal to 3. But if pi had started out being 3.9, pizza would still end up equal to 3.
Once a variable has a string value assigned, there are lots of neat things you can do with it. You can add more to the end of the string, take out parts of it, look at what the various characters are, and compare one string to another. Here are some activities you can try:
+) sign. Lets say the string adverb has the value very and the string adjective has the value nice. If you enter the command opinion = adverb + adjective, then the variable opinion will have the value verynice. If youd like to add a space (or other text), just put it between quotes and include it in your statement: opinion = "This is " + adverb + " " + adjective + "!"
-) allows you to remove the first occurrence of one string from anoth-381er. So if stress has the value inhibit, the command stress = stress - "i" will give it the value nhibit.
/), which is also used for dividing numbers. If stress once again has the value inhibit, then the command stress = stress / "i" will give it the new value nhbt.
> (greater than) and < (less than) to compare strings. Earlier in alphabetic order is considered less than and later in alphabetic order is greater than. So if animal has the value aardvark and toy has the value ball, the statement comp = animal < toy will give the value true to the variable comp.
a has a value of 12 and a type of long and b has a value of dozen and a type of string, then the statement b = a + b will give b the new value 12dozen.
Date and time variables are interesting because they share properties of both numbers and strings. Nisus Writer has a number of predefined date and time variables (e.g., date, DayOfWeek, year) that store different parts of the date or time. When you set another variable equal to one of these, your variable also takes on the date/time type. Date/time variables can be treated like numbers. For example, you can compare two dates as you would compare numbers, and the later date will evaluate as the larger number. This macro will give you a result of true:
vacation = date + 12 work = date + 9 schedule = vacation > work clipboard = schedule :1 '\CC'
382 But you can also treat date/time variables like text. For example, if you assign the date to a string variable, the string will have the text form of the date as its content (the format is determined by the preference you set with the Date Format
command on the Variable Stamp submenu of the Tools menu). In this example, the macro will display the date as text:
RightNow = "" RightNow = date clipboard = RightNow :1 '\CC'
As we have seen, strings go inside (double) quotesthats how a macro can tell theyre strings and not variable names, commands, or who knows what else. In Nisus Writer macros, double quotes always mean, This is a string. That being the case, how do you get the quote character (") into a string? Lets say we want the string quote to have the value A "fine" time. If we use a statement like quote = "A "fine" time" then the macro will get confused because it doesnt know what to do with all those quotes. Next we might try something like quote = "A " + """ + "fine" + """ + "time"that is, putting a quote character itself within quotes, and separating that out as another string. Unfortunately, that doesnt work either. But it can be done! The trick is to use the ASCII value of the quote character directly instead of typing the character. It so happens that the quote is ASCII 34. So we can use the special command NumToChar (number to character) to make the conversion. It works like this:
qm = NumToChar(34) quote = "A " + qm + "fine" + qm + " time"
and that, in fact, does the trick. Use NumToChar any time you need to put a quote mark into a variable or onto the clipboard without actually copying it from your document.
|
|
These acrobatics are only required in the Programming Dialect. In the Menu Command Dialect, if you want to include quotes in an argument, just type them twice within another set of double quotesfor example, to find and select the next quote mark, use the command Find Next """". |
|
|
383 If theres a variable that youd like to use with the same value in all of your macros (like qm above), make it a global variable and assign it a value in your InitInit macro. That way it will assume that value automatically whenever that macro file is opened. The macro might read global qm; qm = NumToChar(34). |
There are also times when youll need to use single quotes around an expression. For arguments to Menu Command Dialect commands, single quotes mean that the macro evaluates the expression before doing whatever the command is. That is, it turns any metacharacters into real characters, and in the case of clipboard variables (see the next lesson), replaces the variable with the contents of the clipboard. For example, Paste "" 'horse \t buggy' will paste the word horse followed by a tab and the word buggy. But the command Paste "" 'horse \CC buggy' will paste the word horse followed by the contents of the current clipboard and the word buggy.
Lesson 5: Using the Clipboards
We already know how to use the Cut, Copy, and Paste commands in macros, how to switch clipboard numbers, and even how to move the contents of one clipboard to another. But in addition to being temporary storage places for things that youre moving around your document, clipboards can be thought of as a kind of variable. Because of this fact, there are special ways of dealing with the clipboard in macros that give you some additional capabilities over regular menu commands. Well look at some of the other uses of clipboards in macros in this lesson.
Whenever you do a Cut or Copy (either manually or as part of a macro), you store something on the clipboard. The contents of the current clipboard can be used within a macro by using the word clipboard as though it were a variable. Here are some examples:
Cindy = clipboard puts the contents of the clipboard into the variable Cindy.
clipboard = clipboard + 25 adds 25 to the contents of the clipboard (assuming theres a number on the clipboard).
clipboard = clipboard + "25" appends the string 25 to the contents of the clipboard (assuming the clipboard contains text).
384 Since clipboard is a variable, you can also put things on the clipboard without having to cut or copy. And because it is part of the programming dialect, the things that go on the clipboard can be the values of variables, mathematical expressions, and so on. For example:
clipboard = "Caffeine rocks."
clipboard = Cindy + cos(x)
clipboard = "I dont think that " + ArtForm + " is a valid art form."
There are times, though, in which you cant achieve the desired result using the variable clipboard, because in some contexts (like arguments), what is required is a string rather than a variable. For instance, you may want to name a new document with the string thats on the clipboard. If you tried to use the command New clipboard to do this, Nisus Writer would have no idea what you mean. And if you tried New "clipboard" the new file would be named clipboard! So you need a way to access the clipboard as a string instead of a variable. As youll recall from working with PowerFind Pro, the metacharacter for Current Clipboard is \CC. And as we saw in the last lesson on variables, using single quotes around an expression causes it to be evaluated before it is used. So if you put it together, you get the expression '\CC' which means the contents of the current clipboard. '\CC' can be used anywhere a string in double quotes canincluding as an argument to commands like Find/Replace, and Jump To. For example:
New '\CC'
Find/Replace "king" '\CC' "gaAt"
As in PowerFind Pro, not only '\CC' but also '\C0' through '\C9' can be used this way to access the contents of all ten clipboards. To switch the number of the current clipboard, you need to use one of the (Menu Command Dialect) commands 0 through 9 on a line by itself.
There are several ways of interacting with the user during a macro. The reason they are included in this lesson is that they frequently make use of the '\CC' command weve just learned.
The first thing you can do is present a simple alert dialog box containing text of your choice. To do this, use the command :1 followed by the text you want to appear in the dialog box, enclosed in straight quotes. For example, :1 "Hello there!" will display the dialog box in Figure 12.13. To use the contents of the clipboard as the displayed text, use the command :1 '\CC'. A typical use of this construction is to display the value of some variable, as in the following example:
Var = DocPath clipboard = Var :1 '\CC'
All alert dialog boxes displayed in this fashion have exactly one buttonOKand nothing else will happen until the user clicks this button.

Figure 12.13. A simple alert dialog box created in a macro.
You can also use this alert as a means of getting input from the user at any point in your macro. All you need to do is add a second argument (that is, a second pair of straight quotes), and a text entry field will be added to the dialog box. Your command might then look something like :1 "Enter a name." "" (see Figure 12.14). If you want to provide a default answer that will be filled in automatically (so that the user just has to click OK if thats the desired response), place that text 386 between the second set of quotes: :1 "Enter a name." "Bob". The contents of the clipboard can be used as either argument, by substituting the '\CC' statement for the quoted argument (as in :1 "Enter a name." '\CC'). You can even include the contents of the clipboard within a string of text by surrounding the entire text with single quotesfor example, :1 'Whats so great about \CC? Im telling you, \CC is not the answer.' 'But I like \CC!' (observe that since the entire argument is in single quotes, you dont need single quotes around \CC too).

Figure 12.14. An alert dialog box with a text entry field allows you to get input from the user during a macro.
When your alert dialog box includes a text entry field, whatever the user types in is placed on the current clipboard when OK is clicked. If the text entry field is left blank, then the clipboard will be cleared. This macro gives you an idea of how the :1 command gets and processes input:
:1 "Enter a color." "" Col = clipboard :1 "Enter another color." "" Sentence = "Roses are " + Col + ", violets are " + clipboard + "." clipboard = Sentence :1 '\CC'
|
|
Though we mentioned it before, its worth repeating: the :1 command is part of the Menu Command dialect, not the Programming Dialect. This means that you cant use a variable name, mathematical expression, or the like as an argument to :1statements like :1 Wanda or :1 cos(3) will produce an error message. |
Before we end this lesson, I wanted to mention briefly two other ways of interacting with the user. First is the Speak command (again, part of the Menu Command dialect). Your macro can speak any text as an alert. You simply type the text you want spoken as an argument of the Speak command: Speak "How very nice to be working with you again." Or, to speak whatever is on the clipboard, use '\CC' (with or without additional text)for example, Speak 'You are very \CC'. Make sure your computers volume is turned on before using Speakthere is, annoyingly, no macro command to adjust the volume! Also, be aware that while the speech engines 387 pronunciation is far from perfect, you can often make it sound a lot better by spelling out words the way you think they should sound. For example, the command Speak "Now reformatting your hard drive" doesnt sound very convincing, but if you change it to Speak "Now reeformatting your hartdrive" youll find the inflection much more natural. Try it!
And finally, there is the simple command Beep. This command, which is also part of the Menu Command Dialect, will simply play your currently selected system alert sound once.
Lesson 6: Labels, Subroutines & Loops
So far, all of our macros have run in linear order from start to finish. But there are times when you need more flexibility than that. For one thing, you may want a macro to repeat some activity multiple times (without having to copy the same part of the macro over and over). For another thing, you may want all or part of your macro to run only under certain circumstancese.g., do one thing if the user gives one type of input, and another thing if the user gives a different type. And of course, if you are trying to break down your macro into small chunks to work with, it would be helpful to have an easy way to label, refer to, and run any particular chunk. In this lesson well talk about the mechanisms that let you do all of these things.
A label is a word whose only purpose is to mark or identify a certain spot in your macro that can be jumped to easily. A label is created by typing a single word, followed by a colon, on a line by itself (no spaces allowed). Label names are completely arbitrary, and you can use any word you want. When you want to jump to a labeled part of a macro, type Goto followed by the label name (without the colon). Heres an example you can type in and try.
Select All Goto France Bold Italic France: 18 Red
388 In the first line, the Select All command is performed. In the second line, the command Goto France tells the macro to go to the line labeled France: and continue from there. So it skips the commands Bold and Italic and goes on to make the text 18 points and red. Of course, there wouldnt be any point to including extra lines in a macro if youre always going to skip over themthats where conditionals come in, which well talk about next. But there are just two simple points to absorb here. First, you make a label by putting a word, followed by a colon, on a line by itself. Second, you jump to the label using the Goto command.
In some cases, its O.K. for your macros to press on with their assigned tasks blindly. Often, though, you will want for some part of your macro to run only if certain things are trueonly if your document contains a certain word or only if the user responds a certain way to an alert, for example. In other words, youd like the macro to be able to check one or more conditionsstates that may be true or falseand act accordingly. The statement in Nisus Writers macro language that lets you do this is the If() conditional test. It is often used in conjunction with Goto, but as well see it has other uses as well.
The If() statement allows you to say, in effect, If such-and-such is the case, then do this. The condition, or that which is being checked for its value, is what goes in parentheses. When a macro comes to the If() statement, it looks at the condition and evaluates itdetermines what its value is (true/false, a number, or a string). If the condition evaluates to true (in the case of a logical statement), a non-zero number (if its a mathematical expression), or a non-empty string (if its a string variable), then whatever comes after the parentheses will be executed as a (programming dialect) macro command. If the expression evaluates to false, zero, or an empty string, the command after If() will simply be ignored; there is no Else statement in Nisus Writer. In the examples that follow, Ill concentrate on the true/false evaluation.
|
|
You can also say, If such-and-such is not true, then do something. To create a negative If, use an exclamation point (!) as the first character inside the parentheses. For example, the command If(!x == 3) goto Egypt says, if its not true that x is 3, go to the line labeled Egypt. This is the same as saying If(x != 3) goto Egypt. |
|
|
Be careful not to include a command after If() that isnt part of the programming dialect. For the record, the command that follows If() cannot be a menu command, the Key command, or the alert (:1) command. |
Lets look at a really easy example: If(4>3) Goto AddNumbers. This command says, If it is true that 4 is greater than 389 3, then go to the line labeled AddNumbers: and proceed from there. Since we know that 4 is always greater than 3, the condition is true and this line would always make the macro jump to the AddNumbers: label. Needless to say, theres very little point in making a conditional statement if whatever youre evaluating is always true (or always false). So what you want to put inside the parentheses is a statement having a value that can change. If we change the statement to If(x>3) Goto AddNumbers, then the command Goto AddNumbers will be executed or not, depending on what value the variable x has at the moment. Another form the conditional statement can take is testing whats on the clipboard. The statement If(Clipboard == "Suzie") Goto MainLoop first determines whether the current clipboards content is the name Suzie (and nothing else), and then if so, jumps to the MainLoop: label.
Notice that in If() constructions, we need to use double equal signs (==) instead of a single equal sign (=). In Nisus Writers programming dialect, = means is now being made equal to, and is used to assign a value to a variablefor instance, a = 2 means I hereby set a to the value of 2. On the other hand, == means simply is equal to in the ordinary sense, and can be used as part of a test to come up with a true or false value.
With this in mind, lets return to the macro we used above and make some modifications:
Select All :1 "Where should I go?" "" if(clipboard != "France") goto Italy 18 Red goto MacroEnd Italy: Bold Italic MacroEnd:
First, after the Select All command, we give the user an alert and an opportunity to give some input. If the user types in anything other than France (note the != sign), the macro will skip to the Italy: label and make the text bold and italic. But if the user does type in France, the condition will not be 390 met, so the Goto command will not be performed. The macro will continue on to the next line, making the text 18 points, then red. When it comes to the line that says goto MacroEnd it will skip to the last line of the macro, and finding nothing left to do, it will quit.
While the If() statement is most often used to evaluate the clipboard or a variable, then jump to another part of your macro, there are other things you can do with it. Here are a few examples just to give you an idea, followed by plain English translations:
If(x <2 || x > 12) y = 5 If x is less than 2 or x is greater than 12, then set y equal to 5.
If(Error) Exit If an error was produced by whatever just happened, stop the macro. The word Error is a special predefined variable that has a value of true when an error has occurred in your macro, and false the rest of the time.
If(Clipboard != "yes") Macropaste If the clipboard does not contain the word yes (only), then paste the text currently on the clipboard at the insertion point in the document window. You cant use the Copy or Paste after If(), because theyre part of the Menu Command Dialect. Instead, use Macrocopy and Macropaste (see Appendix C).
If(!Coffee) clipboard = "refill" If the variable Coffee is not a non-empty string (in other words, its an empty string), then put the word refill on the clipboard.
In traditional programming, a subroutine is a kind of program-within-a-program. Typically the program is performing a series of steps, then it comes to a command to perform a subroutine. It jumps to the part of the code containing the subroutine and runs that. After the subroutine has finished, the program automatically goes back to where it left off and continues its work. Some programming languages have a special command like GoSub which specifically means, 391 go and do this other thing, but when youre done, come back! Nisus Writer accomplishes the same thing in a different way: a subroutine can simply be another macro. To have one macro activate another, put the second macros name on a line by itself (after all, it is a menu command), and when the second macro is finished (unless a Stop command is encountered), the first macro will pick up where it left off. When one macro sends a command to run another macro, it is said to call the second macro. Figure 12.15 gives an example of a subroutine.

Figure 12.15.Subroutines in macros: one macro activates another.
|
|
A macro can also call itself. If a macro comes to a command which is its own name, it will skip back to the top of the macro and begin performing each command again. This is a kind of loopbut see below under Loops for more advanced ways. |
There is another sense of the word subroutine which is a little less exact, but also quite important. You can think of a subroutine as simply a smaller portion of a macro that does a particular job, whether or not you actually return to the place you left off later. Subroutines in this sense are invariably accessed using the Goto command, usually in conjunction with If(). When a macro chooses between one path (subroutine) and another based on some condition, this is known as conditional branching. Macros can include any number of branches, and sometimes the path the macro follows can become quite complex. But note that you cannot say If(test) Goto MacroName (or If(test) MacroName), since commands calling other macros are considered part of the Menu Command Dialect.
When working with macros that involve calling other macros or performing these pseudo-subroutines, its important to know how to end a portion of your macro (and optionally go on to another portion). Weve already seen the 392 Stop command, which stops not only the current macro, but also any macro that may have called the current macro. Another way to stop a macro is to use the Exit command. It will exit the current macro, but if another macro had called it, it will go back to where that macro left off and allow it to continue. The third way to end a subroutine is to use the Goto command again. In addition to jumping to another portion of your macro, you can have Goto jump to a label that appears at the very end of your macro to end the macro without using Exit or Stop (as we saw a short while ago). The following fairly pointless macro illustrates some ways of performing one sequence of activities or another, based on user input:
:1 "Go to bed or watch a movie?" "bed" if(clipboard != "movie") Goto Bed :1 "What do you want to do now?" "study" if(clipboard != "study") goto FinishNext :1 "What is your favorite subject?" "philosophy" clipboard = "I love to study " + clipboard + "!" :1 '\CC' FinishNext: Goto Finish Bed: :1 "Good night!" Goto Finish Finish: :1 "This macro is about to end." Exit
There are a few things you should notice here. First, the macro is arranged to run in linear order, no matter what the user chooses. Second, some seemingly superfluous labels and Goto commands have been used; the idea is to have them there so that the macro could be expanded or added to later without a lot of reworking. Try to figure out the path this macro would follow given different combinations of input, then try running it to test your skills!
A loop is part of a macro (or the whole thing) that is repeated. There are any number of things you might want to do repeatedly, especially if they involve getting new input from the user each time. Now that you know how to use Goto, it should be pretty obvious how to make a loop (at least a simple one): end a labeled portion of your macro with a Goto command that refers to the same label again. So you might have something like this:
:1 "Where should I go?" "France" If(Clipboard == "France") Goto France :1 "Goodbye!" Exit France: :1 "What is your favorite number?" "5" :1 'No kidding! \CC is my favorite number too!' Goto France
Theres just one teensy problem with this: the loop never ends! So the problem with loops is not so much how to get into them, but how to get out!
The key to getting out of loops is to include some kind of hooka conditional statement or other command that will exit the loop (or the entire macro) under certain conditions. Lets look at a few ways to do this. One way is to ask the user, each time through the loop, whether the macro should continue. So we could modify the subroutine like this:
France: :1 "What is your favorite number?" "5" :1 'No kidding! \CC is my favorite number too!' :1 "Do it again?" "No" If(Clipboard != "No") Goto France
In other words, we have to get permission in order to continueotherwise, we quit.
Another way is to use a counter (discussed in more detail in Lesson 7) to restrict the loop to a given number of 394 passes. This works by adding 1 to a variable each time through the loop, and including a command that stops the macro if the variable gets to a certain number. For example:
x = 0 France: x = x + 1 :1 "What is your favorite number?" "5" :1 'No kidding! \CC is my favorite number too!' If(x < 5) Goto France
Here, we start out by giving x a value of 0 before the loop, and each time through the loop we add 1. When x gets to 5, the macro ends.
The last way of adding a hook to a loop (sounds like Velcro, doesnt it?) is to use the "T" option in a Find/Replace command. "T" means Terminate the macro if nothing is found. So if your loop is doing a series of replacements and you want the macro to end when it runs out of things to replace, use the "T" option after the Find/Replace command.
Branching conditionals, subroutines, and loops are very powerful, and also lots of fun to experiment with. After some practice, youll be able to thread your way through very complex activities without any trouble at all. But remember, it does take practice to get the knack of how to break things up, where to put Goto commands and so forth. Be sure to check out the many macros on the enclosed CD-ROM for samples of these constructions. And one final thought: if all else fails, try sketching a flowchart of the path you want your macro to take before actually writing the macro. You may find, as I do, that this helps you to organize the flow of your thinking more easily (as well as catch some bugs before they happen).
Lesson 7: Working with Numbers
This is going to be a fairly short lesson, since we already talked quite a bit about numerical variables in Lesson 4. However, there are a few other important things you should know about numbersspecifically, counting, doing math, and using random numbers.
One important use for numeric variables is to act as countersvariables that increment (or decrement) with every pass of a loop. There are several reasons you may want to keep track of how many times a loop has been run. For one thing, you may want the loop to execute only a limited number of times. Using a counter, you can add 1 to the value of a variable each time through the loop, and then check to see if it has reached your limit. If it has, you can tell the macro to exit or branch somewhere else. Another reason is to keep track of your progressletting you know how many times a macro loop has run so far (using Speak, perhaps).
To make a counter, assign a number (usually 0 is best) to a variable. Make sure this assignment is done outside the counting loop, or it will be reset each time! Then, add a label to begin your loop, and enter a command like Counter = Counter + 1. This will add 1 to whatever the counters previous value was. Then, include a command to do something with that number, like report it to the user or check to see if its gotten too high. Heres a brief sample macro that does both, by counting out loud from one to ten:
Counter = 0 loop: Counter = Counter + 1 clipboard = Counter Speak '\CC' If(Counter < 10) goto loop Speak "Im done now."
Nisus Writers macro language offers a full range of mathematical and trigonometric functions that can be used to perform nearly any kind of calculation within a macro. These are all listed in Appendix C. Most mathematical operations can be performed using familiar operators (symbols that indicate an operation is taking place) like +, -, *, and /. The mathematical functions, however, generally ask for one or more 396 arguments in parentheses, for example sqrt(16) or fmod(5,3). Functions and operators can be combined freely in a given statement, for expressions like y = sqrt(3+13) / floor(18.239) * log(5*5) or x = 12 * sqrt(fmod(3,5)). Since math in Nisus Writer macros is so straightforward, I will not go into any more detail here, except to remind you that all mathematical operations are considered part of the Programming Dialect, and will produce an error if you try to put them on the same line as a Menu Command Dialect command.
There are times when youd like a macro to behave a little unpredictably. On such occasions, you can use either the function random, which chooses a random integer, or rrandom, which chooses a random floating point number within a given range. Ill give you a simple example of how these commands could be useful. Every month at Nisus Software, we hold a random drawing of the entries to the electronic Guest Book on our World Wide Web site, and award the lucky winner a free T-shirt or other prize. We dont bother printing out the entries and pulling one from a hat; we use a macro to choose. It asks what the total number of entries was for the month, then selects a random number in that range. Since all of the entries are numbered as they come in, we simply find the message with the winning number and send the winner a congratulatory note.
Heres how you use random. To have Nisus Writer pick any random number in the range 32767 to 32767, you simply use random all by itself, assigning a variable that value. Heres a macro that will display the random number:
number = random clipboard = number :1 '\CC'
However, the number that this macro generates may be either positive or negative. If you want to restrict the output to positive numbers, you can add the fabs() function, which takes the absolute value of a number (i.e., the number without a + or sign). So the revised command would be number = fabs(random). Now lets suppose you want to make sure the number is no 397 higher than 100. To do this, you add a percent (%) sign after the command random, followed by the maximum value (the minimum value is always assumed to be zero). The command would now be number = fabs(random%100).
But what if you dont want zero to be the bottom of the range? What if you want a random number between 150 and 250? Simple: just add 150 to the random number chosen. In other words, the range from 150 to 250 is 100 units large. If we take the minimum value of fabs(random%100), which is 0, and add 150 to it, we have the minimum value within the range we want. And if we take the maximum value of fabs(random%100), which is 100, and add 150 to it, we have 250, the maximum value in our desired range. So our final macro looks like this:
number = fabs(random%100) + 150 clipboard = number :1 '\CC'
If you want to decrease the rangefor example, look for numbers just between 150 and 175then change the value after the % sign (e.g., fabs(random%25)+150).
Lesson 8: Arrays, Stacks, and Queues
Variables, as we have seen, are wonderfully useful objects, but they can only store one value at a time. There are many cases in which it is useful to store many values in the same place. For example, lets say you have a macro that will create random sentences by putting together a noun, a verb, and another noun. You might want to have a list of possible verbs that the macro can choose among when it gets to the right place. However, just using ordinary variables, youd have to give each possible verb its own variable name, and then come up with a clever way of choosing one of the variables. It would be much easier if you could say, This special variable contains ten different verbs; pick one of its possible values. In this lesson, well look at a variety of ways to do just that, using a kind of storage device known as an array.
An array is basically just a list, like a list of words, numbers, or things to pick up at the store on your way home. This list can contain any number of items, and you can refer 398 to each item individually by number if you like. Or you can talk about just the first item, or just the last item, for example. You can remove things from one end of the list, or add things to either end. However, you cant add new things to the middle of the list or remove things from the middle. While all arrays in Nisus Writer are the same kind of object, they are not always treated like ordinary liststhere are two additional metaphors for referring to them: the stack and the queue. At any moment, you can treat an array as either an ordinary array, a stack or a queue, and the way you choose to look at it will influence what you can do with it and what commands youll use. Well talk about stacks and queues shortly; first, lets look at raw arrays.
|
|
If youre a programmer, you may be surprised to find that a stack and a queue are not two different things in Nisus Writer. Youll also be surprised to know that an array can contain any combination of data types (numeric, string, etc.) at once. There may be other surprises as well. My advice: take this material at face valueitll make a lot more sense! |
Lets create a simple array. To do this, well use the command create. When using this command, you need to decide up front how many elements (slots) you want the array to have (keeping in mind that you can add to it later on). Lets start with 5. We also need a name for our arraylets call it Clyde. To create an array named Clyde with 5 elements, we use the command: Clyde -> create(5), which says: Apply the method create to the array Clyde using a value of 5. The symbol -> (a hyphen followed by a greater than sign) is called the method operator, and what it does is apply the method on its right to the array or variable on its left. A method is, for our current purposes, a way of accessing data. The method we just used is that of creation. And the create command requires a specific value, which is placed inside parentheses after it. So what weve done is created an array (a list) named Clyde with 5 empty slots.
Putting values into the slots, and getting them back out, is done just the way it is with regular variables, except that you refer to the slots by their number, which goes in brackets. So to put the string baseball in slot 3 of the array, wed enter Clyde[3] = "baseball". You can repeat this procedure for each slot. To use the contents of a slot, once again you can treat it like any variablefor example Clipboard = Clyde[3] would put the word baseball on the clipboard.
399 In addition to referring to a particular slot by number, you can refer to a slots position relative to the last slot that was accessed. The relative slot numbers are placed inside double brackets. The number you use is added to the last value accessed to determine the current value. For example, if after saying Clyde[3] = "baseball", you enter Clyde[[2]] = "popcorn", the word popcorn will be placed in slot 5 of the array Clyde. The 2 (inside double brackets) is added to the last value used (3) to arrive at the current value of 5. Relative numbers can be positive, negative, or zero (zero refers to the same value that was used last time).
You may be wondering how arrays are actually used in macros. Heres a quick example. Lets create a shopping list with three items. Then well ask for input: you can choose a number from one to five and the macro will tell you which item is stored at that location in the array. Not very impressive, but it shows how arrays are constructed and used:
list -> create(3) list[1] = "cookies" list[2] = "milk" list[3] = "tofu" :1 "Which item do you want to see (13)?" "" ListNum = clipboard clipboard = "Item " + ListNum + " is " + list[ListNum] + "." :1 '\CC'
Think back to your high school cafeteria. If yours was anything like mine, there was a big contraption at the beginning of the food line which held the trays. Funny thing, though: the stack of trays was always at the same height. This happened because there was a big spring-loaded mechanism that would compress or expand as needed. When you took a tray off the top, the rest of the stack would pop up, and if a stack of new trays got put on top, theyd all get pushed down so that the top stayed at a constant height. Of course, this also meant that you couldnt just reach into the stack and grab any tray you wantedyou had to take the 400 one off the top, and if somebody put another tray on, the only place in the stack it could go is on top.
The point of this tale is that if you understand how the cafeteria tray holder works, you know everything you need to know about stacksone of the ways of looking at arrays in Nisus Writer. A stack can hold any number of different values at one time, but with a catch: when you add new values to the list, you can only push them onto the top of the stack, and when you remove them, you have to pop them off the top in the reverse of the order that they were pushed. So lets look at how we can push or pop values in an array.
The command push() will put a new value onto the top of a stack, top in this case being slot 1. Lets see how this works. Suppose we have an array with two elements:
Fred -> create(2) Fred[1] = "coffee" Fred[2] = "tea"
Now we want to add a third element, but we want to push it onto the top of the stack. We add this command:
Fred -> push("milk")
This says, Apply the method push to the array Fred using a value of milk. Now, if we were to look at the values in the array, wed find that Fred[1] is milk, Fred[2] is coffee, and Fred[3] is tea. So the new value assumed position 1 and pushed the other values down one. Note that you dont need to use the create command before using push()the first time you use push with an array, it will create the necessary number of elements if theyre not already there.
The other part of the stack metaphor is the pop command. It does the opposite of pushit gives you back the first (top) value in an array, shrinking the number of elements by one. So if we have the same three-element array that we just worked with and entered the command Fred -> pop, the first item would be removed and everything would move up one position. You can also use the pop command as part of another expression, if you want to actually do something with that value rather than just remove it. For 401 example, we could have said clipboard = Fred -> pop, which would have put the first value of Fred (namely, milk) onto the clipboard.
Besides treating arrays as stacks, we can treat them as queues. A queue (pronounced cue) is a line, like a line of people waiting to buy tickets. The first people to arrive are the first to be served; when new people arrive, they need to go to the end of the line. As people are served, they leave the beginning of the line. So a queue works the opposite of the way a stack doesin a stack, you add new elements to the top or beginning; in a queue, you add new elements to the end.
What this means in terms of arrays is that just as you can push() an item into the first position in an array, you can qpush() an item into the last position in an array. If your array is a line of people waiting to be served, you might think of qpush as a new person politely lining up at the end, and push as someone shoving into the front of the line. Or, to use the cafeteria tray metaphor, to qpush an item onto the stack would be to stick it directly on the very bottom (the last item to be used). However, there is no qpop() commandwhile you can find out the value of the last item in an array, you cant remove it directly until the other elements are used.
Arrays have a lot of potential uses, many of which youll see in the sample macros included on the CD-ROM. But theres a set of special keywords that give arrays special power, by referring to any selection(s) in your document, even noncontiguous ones. They allow you to put all the selected elements (text or numbers) into individual elements of an array all at once, or to store all the starting points and/or ending points of all the selections at once.
Lets assume that you have one or more blocks of text selected. If you then have a line in a macro that says Selections -> push(strings), every selected block of text will be stored in an array named Selections, each as a separate text 402 string. To store the selected items as integers, use the keyword ints instead of strings; to store them as floating point numbers, use floats. Instead of storing the contents of the selections, you may want to store just the starting and/or ending points. To store all the starting points, use a command like Selections -> push(starts). To store the ending points, use ends instead of starts. And to store both starting and ending points (in order of selection start then selection end, etc.), use StartEnds.
To get an idea of how this would work, lets construct a simple but very useful pair of macros. The first will store all the selections in your document, and the second will restore them after theyve been deselected. This could be very useful to do if you begin making a lot of selections, then realize you need to copy or work with something else separately, but dont want to lose the other selections. The second macro uses another pair of commands you havent seen yetSetSelect and SetSelectMore, which actually make selections in your text when given arguments that contain the offsets of beginning and ending points. Here is the first macro:
global Selections Selections -> push(StartEnds)
Pretty simple, right? After youve made a series of selections, run the above macro, which well call Save Selections. Now click somewhere to deselect what youve selected. Next, use the following macro, which well call Restore Selections.
SetSelect(0,0) if(!Selections -> size) Exit loop: SetSelectMore(Selections -> pop, Selections -> pop) if(Selections -> size) goto loop:
When you run this macro, all of your selections will be restored (one at a time). Of course, if you make changes to your text before running Restore Selections, all bets are off, because it only counts the number of characters from the beginning of the document, and if the number changes
tough. But if you just deselect the text (or select other text), it will work beautifully.
403 There are quite a few other commands that can be used with arrays, but we dont have space to cover them here. Refer to Appendix C for a complete list with brief explanations, and look through the other macros in this book and on the CD-ROM for examples of how theyre used.
Lesson 9: Scripting with Frontier
While Nisus Writers built-in macro language is quite powerful and capable, you can go even further by using macros to control other applications. This is done by way of Frontier, a system-level scripting environment that can communicate with the Finder or any OSA (Open Scripting Architecture)-compliant application. Nisus Writer includes a copy of Frontier Runtime, and the full version of Frontier 4.0 (a.k.a. Aretha) is available free on-line. To download the latest version or for more information on Frontier, point your Web browser at:
http://www.hotwired.com/staff/userland/aretha/
|
|
The current version of Frontier is now 6, and it can be found at frontier.userland.com/. Unfortunately, it is no longer freein fact, it's obscenely expensive. However, you can still download an older version (5.0.1) for free at www.scripting.com/frontier5/downloads/. |
It is important to emphasize that as yet, Nisus Writer itself is not scriptable, either with Frontier or with AppleScript. Nisus Writer can send commands to other applications, but not receive commands. In order to remote-control Nisus Writer, youll need to use a macro utility like QuicKeys or KeyQuencer, or PreFab Softwares Player program to play the interface from an AppleScript or Frontier script. Future versions of Nisus Writer are expected to address this deficiency.
In what follows, I will not teach you much about Frontier. To learn about UserTalk, Frontiers scripting language, surf to the URL mentioned above or consult Tom Trinkos Applied Mac Scripting (M&T Books, 1995). Here Ill give just a brief sketch of how Frontier commands can be activated from Nisus Writer and included within macros.
There are two Nisus Writer commands that pertain to Frontier: Frontier Do Script
(found on the Macros menu) and Frontier Do Selection (which replaces Frontier Do Script
when you press the Shift key). When you choose Frontier Do Script
, Frontier is launched in the background (if its not already running), and a dialog box appears asking you to type in a Frontier command. After you type in the 404 command and click OK, the command is sent to Frontier for processing. If you already have a Frontier script typed into your document, you can select it and choose Frontier Do Selection (which is analogous to Nisus Writers Execute Selection).
You can also use Frontier Do Script in a macro. It must be followed by a valid Frontier command in either single or double quotesfor example, to place the pathname to the System Folder on the clipboard, youd say:
Frontier Do Script "file.getSystemFolderPath ()"
If the Frontier command itself needs to include something in quotes, then you put the whole command in single quotes. For example, to open the control panel named Monitors, you would enter:
Frontier Do Script 'launch.controlPanel ("Monitors")'
For some reason, double quotes inside single quotes dont always work. One case where they dont work is when youre trying to list the parameters to send an Apple event. This command sends a GetURL event to Netscape using the contents of the current clipboard as the URL:
Frontier Do Script 'appleEvent (''MOSS'', ''GURL'', ''GURL'', ''----'', "\CC")'
To get around the problem of double quotes inside single quotes not working, you need to use a pair of single quotes on each side of the expression. So in the above example, MOSS, GURL (twice) and ---- each have two single quotes on each side; only the command \CC is surrounded by regular (double) quotes. When the \CC command is sent as an argument to Frontier, it is always in double quotes, with the whole expression being in single quotes.
|
|
When you send a command to Frontier, it will return a result (e.g., true or false) on the clipboard. To avoid having the result placed on the clipboard, place the argument "-" at the end of the Frontier Do Script command. |
Theres not much more I can say here about Frontier without giving you a lesson in UserTalk, and thats beyond the scope of this book. However, I do recommend that you check out the macros on the enclosed CD-ROMparticularly the file Joes Internet Macrosfor further examples of what can be done and how to do it.
405 Lesson 10: Debugging
Despite your best efforts, your macros may not always work perfectly the first time. Often, when you run a macro and it doesnt work correctly, the reason is fairly obvious. But other times everything looks right and it still doesnt work. This can be very frustrating, especially if your macro is long and complex. Since there are a nearly infinite number of things that could cause your macro not to work properly, I cant pretend to give you all the answers here. However, I can give you a few helpful hints that will help you to overcome some common problems.
First, watch out for the old mixing dialects in a single line problem. Although as I mentioned when we first talked about this, many people never experience this problem at all, it is a trap thats easy to fall into if youre not careful. Sometimes mixing dialects will produce an error message like the one shown in Figure 12.16. This means that neither the Menu Command Dialect nor the Programming Dialect can interpret the line as an available command. Youll get this same message if you have a menu command in your macro that is misspelled, or another command which for one reason or another cant be found. To avoid problems like this:
Key, :1, and Speak, which are all part of the Menu Command dialect.
clipboard when you would ordinarily need a variable; use '\CC' when a string is called for. And dont forget that those are uppercase Cs.

Figure 12.16. This alert appears when neither dialect can figure out what to do with your command.
Another common problem is trying to manipulate variables before they have been instantiated. For example, the command myVar = 10 is perfectly fine anywhere in your macro. But if you make a statement like myVar = myVar + 10 without first giving myVar some value (and, at the same time, a data type), the macro engine will get confused and display a 406 message like the one in Figure 12.17. To avoid this problem, make sure that the first time you use any variable, you assign it some value (even if the value is 0 or ""), so that the macro will know what kind of variable it is and how it needs to be used. Also, when testing a portion of your macro using Execute Selection, make sure that you have selected the instantiating statement for any variables that are used in your selection; otherwise, the selected part of the macro wont work properly.

Figure 12.17. This alert appears when you try to use a variable before it has been instantiated.
Here are some additional assorted tips for dealing with common problems in macros:
Execute Selection, or by putting a temporary Stop or Exit command in the middle of the macro to interrupt it 407 at certain points. This will help you to figure out what part of the macro has the problem.
Learning More
The possibilities for macros are nearly endless, as you can imagine, and we cant cover every possibility here. But if you want to learn more about writing macros, there are several sources you can consult. First, after working through the examples in this chapter, youll want to consult Appendix C for a complete list of macro commands (not all of which could be discussed here for reasons of space). Each command in the appendix includes a brief explanatory example. Beyond that, for help with macros, you can try any of these things:
Summary
Whew! You made it! Now that you know how to automate your work with glossaries and macros, you are well on your way to becoming the geek you were always meant to be. Im proud of you. Sad though it may be to move on, we have more thrills ahead. Chapter 13 rounds out our Power Techniques section with a discussion of multilingual word processing with WorldScript. Then we move on to the real world with Section IV, Applied Document Processing, in which we put all the pieces together in the context of some actual projects for which Nisus Writer is ideally suited.
Copyright © 1995, 1996, 1999 by Joe Kissell
< Previous Chapter | Next Chapter >