Thió documenô containó thå texô oæ twï articleó oî ZFILEÒ bù Jaù Sagå whicè originallù appeareä iî Thå Computeò Journaì issueó #3¶ anä #37® Reprinteä witè permissioî oæ thå publisher: Thå Computeò Journal P.O® Boø 12 S® Plainfield¬ NÊ 07080-0012 ZFILER, The Point-and-Shoot Shell Now let's turn to the technical subject for this issue, the ZFILER shell. Having written about shells so much in the past few columns, I am tempted to jump right into the thick of the subject. However, judging from the number of new subscriptions that SME alone takes each month, TCJ must have lots of new readers with each issue. Therefore, I will begin at the beginning. Since time and energy are in short supply, however, I will not attempt to provide the same comprehensive documentation that I did for ARUNZ. Instead, I will concentrate on the basics, on the one hand, and on some of the special features that many users may overlook, on the other. Z-System Shells A Z-System shell is a program that takes over the user-input function of the command processor. The way this works is that the Z-System environment includes a special area in memory called the shell stack where shell command lines can be kept. Whenever the ZCPR3 command processor is finished processing all the commands that have been passed to it in the command line buffer (another special area in memory), it checks the shell stack. Only if no command line is present there does the command processor itself prompt the user for the next command line. If there is an entry in the shell stack, then that command line is run instead, and the user no longer sees the command processor directly. Some shells, like the EASE history shell, while making a big change in how the system is actually running, make relatively little change in how it appears to run. A command prompt is still presented, and one enters commands more or less as usual. The difference is that one has a more capablå editoò aô one'ó disposal¬ anä thå commandó arå saveä tï á historù filå froí whicè theù caî bå recalled¬ edited¬ anä ruî again® Aó wå shalì see¬ thå ZFILEÒ shelì presentó thå useò witè á dramaticallù differenô useò interface. What is ZFILER For? Historically, ZFILER is a descendant in the line of file maintenance utilities like SWEEP and NSWP (hence the "filer" part of the name). File maintenance is generally concerned with copying files, looking at their contents, renaming them, erasing them, and so on. ZFILER provides all these functions and more. ZFILER's immediate parent was VFILER, where the "V" stood for video. The TCAP facility in Z-System makes it easy for programs to take advantage of the full-screen capabilities of whatever video display terminal happens to be in use at any time. In contrast to applications under CP/M, Z-System programs need not be configured to match the terminal. It was, therefore, natural to build a file maintenance program in which the files are displayedŠgraphically on the screen. When I decided to explore some new directions with VFILER, to avoid confusion I gave the program the new name ZFILER, for Z-System Filer. The file maintenance tasks described above would not require a shell. Making the program a shell, however, allows it to go beyond the functions included in the program's own code. Because a shell can pass command lines to the operating system, ZFILER can perform any operation that the computer is capable of. Like a menu system, however, it helps the user by generating the commands automatically at the touch of a key. When ZFILER is running, the screen is filled with an alphabetized display of the files in a specified directory, and there is a pointer that the user can manipulate using cursor control keys. If we had a mouse to move the pointer, it would be a little like having a Macintosh. Actually, it would be a lot more. It would be like having a mouse with fifty buttons! Once the pointer has been positioned on a file, pressing a key (or two or three© causeó anù oæ á greaô numbeò oæ functionó tï bå invokeä tï acô oî  thaô file® Wå wilì describå ho÷ thió workó iî morå detaiì shortly. Invoking ZFILER Since ZFILER performs full-screen operations, a proper Z-System terminal descriptor (TCAP) must have been loaded. If you have not done that, or if you have selected a terminal that does not support all the functions ZFILER needs, then ZFILER will give you an error message. The TCAP, unfortunately, does not include information about whether dim or reverse video is used by the terminal, and since these two modes for highlighting regions on the screen are so different, ZFILER is made available in separate versions for each. There is also an option to have either four or five columns of file names in the display. Personally, I prefer the four-column version, which gives an uncluttered screen with plenty of restful white space and a very distinct¬ easù-tï-spoô pointer® Otheró thinë iô ió morå importanô tï bå ablå tï seå thå maximuí numbeò oæ fileó oî eacè screeî anä prefeò thå fivå-columî display. Then there is the issue of support for time and date stamping of files. ZFILER contains the code for preserving the time stamps when files are copied. So as not to inflict the overhead of this code on those who have not implemented DateStamper (though they should do that!), ZFILER is also provided in versions with and without the DateStamper code. If we supported all combinations of the above choices, there would be eight different versions of ZFILER. Typically, the distribution library contains four or five of the combinations. For example, a five-column file display is not particularly compatible with reverse video highlighting, because the reverse video of tagged files runs into the reverse-video pointer. When you get ZFILER, you have to choose which version you prefer, extract it for the distribution library, and give it a working name (some of the early Z-System shells had to have a specific name, but you can give ZFILER any name you like). I prefer the name ZF, since it is very quick andŠeasy to type, and I will use that name in all the examples that follow. The general syntax for invoking ZFILER is ZF filespec where "filespec" is a standard Z-System ambiguous file specification (that is, it may contain the wildcard characters "?" and "*"). The filespec selects the directory area and the files from that area to be included in the screen display. Various parts of the filespec can be omitted. If no filespec is given at all, then "*.*" for the currently logged directory is assumed. Similarly, if only a directory is specified (e.g., B: or 3: or B3: or WORK:), then all the files ("*.*") in that directory are displayed. If a file name/type is included, then it will serve as a mask on the files to be displayed. Thus "ZF WORK:*.DOC" will show only files of type DOC in the directory WORK:. The directory and file mask can both be changed from inside ZFILER as well using the "L" or LOG command. I bring this up now because there is a confusing difference in the way the "L" command works. VFILER originally allowed one to change only the directory and not the file mask from inside the program. To save the user the trouble of typing the colon after a directory, its inclusion was made optional. Since users became so accustomed to this shorthand, it was carried over into ZFILER. Because of this, if you want to change only the file mask, you must remember to precede it with a colon. Otherwise your mask will be taken as the name of a directory (which generally results in an error message). One brief aside for programmer types. ZFILER can be loaded from any directory. One of the special features of Z-System since version 3.3 of the command processor allows a program to find out both its own name and the directory from which it was actually loaded, perhaps as the result of a path search. ZFILER builds the shell stack entry to invoke ZFILER under its current name from the directory in which it is actually located. This sometimes makes it run faster, and it allows ZFILER to be invoked from a directory that is not on the search path. The ZFILER Display The main ZFILER display contains three parts. At the top of the screen there is a message line. In the version of ZFILER that is current at the time I am writing this column (version 1.0L), this line contains, from left to right, the following information: (1) the directory that has been selected, in both DU and DIR (named directory) format; (2) the indicator "[PUBLIC]" if that directory is a ZRDOS public directory (if you don't know what this is, just ignore it); (3) the current time of day if DateStamper or one of the new DOSs (ZSDOS or ZDDOS) is running; (4) the program's official name and version; (5) the text string "Current File:"; and (6) the name of the file currently being pointed to (this changes as the pointer is moved). At the bottom of the screen is a command prompt of the form Command? (/=Help, X=Quit): Š The cursor (don't confuse this with the file pointer) is positioned after this command prompt to indicate that ZFILER is waiting for you to press a key. The center 20 lines of the screen show the selected files. The character string "-->" (only "->" in the five-column display) floats between the rows of file names and designates the so-called "pointed-to" file. Many of the ZFILER commands automatically operate on this file. What we have described so far is the main ZFILER screen, but it is not the only one. As the command prompt suggests, pressing the slash character (or "?" if you prefer) brings up a help screen that summarizes the built-in commands of ZFILER. This help screen replaces the file display but leaves the status line at the top and the command line at the bottom, except that "/=Help" changes to "/=Files". As you might, therefore, guess, pressing slash again will take you back to the file display screen. I do not know if anyone makes use of this feature, but all ZFILER command operations can be invoked from the help screen. Although you cannot see the file pointer, you can manipulate it in the usual way, and you can tell what file you are pointing to from the name displayed at the upper right on the status line. ZFILER Commands I am not going to attempt to describe all of ZFILER's commands, but I will try to list most of them. Basically, the commands fall into several classes. One classification reflects where the code for the command resides. There are two categories: A. Built-In Commands B. Macro Commands Class A includes the functions for which the code is part of ZFILER. Macro commands are like aliases in that they generate command lines that are passed to the command processor for execution. These commands make ZFILER a shell. In this column I will discuss only the built-in commands, and I will take up the more complex subject of macro commands next time. A second classification depends on what the command acts on. Three categories describe the object of the commands: 1. the pointed-to file 2. a group of tagged files 3. neither of the above We will begin the discussion with commands of class A3, resident commands that do not perform any action on the files. Pointer Commands Class A3 includes the commands that move the file pointer. These areŠshown on the help screen, and I will not list them here. One can move the pointer to the next file on the screen or to the previous one (with wraparound); up, down, left, or right (with wraparound); to the first or last file on the current screen; or to the very first or very last file of those selected by the file mask. One can advance to the next screen of files or to the previous screen. Obviously, some of these functions will be redundant in some cases, such as when all the selected files can fit on one screen (think what happens when there is exactly one file selected). ZFILER learns from the TCAP the control characters sent by any special cursor keys on the keyboard (provided they send a single control character and provided the TCAP has been set up correctly), and it makes them generate the up, down, left, and right functions. If the cursor keys generate control codes normally used for another function, then that function will be lost (the cursor keys take precedence). That can cause problems. One solution is to eliminate the definition of the cursor keys in the TCAP and simply use the default WordStar diamond keys for those functions. Alternatively, one can patch ZFILER to use different keys for its own functions, but this is not straightforward to do, and I will not describe it here. The "J" (Jump) command allows you to jump to a file that you name. This is very handy when there are many files in the display or when the file you want is not on the current screen. Press the "J" key, and you will be prompted for a file name. You do not have to enter the exact name. ZFILER automatically converts what you type into a wildcard filespec, and it finds the first file that matches. For example, if you enter only "Z" followed by a return, this is equivalent to "Z*.*", and ZFILER will move the pointer to the first file that starts with a "Z". Similarly, if you enter ".D", ZFILER will move to the first file with a file type that starts with "D". The "J" function is very handy; however, there is more. Many people are not aware that you may press control-J to repeat the same search and find the next matching file. The search will wrap around from the end of the files back to the beginning. This function is not listed on the help screen because I could not find room for it. Other Non-File Commands Some other commands that do not act on files are: X, L, A, S, E, H, Z, and O. "X", as the command prompt reminds you, is used to exit from ZFILER. Besides terminating the current execution of the program, it also removes ZFILER's entry in the shell stack (if it did not, you would just reenter it right away). We already spoke about the "L" (Log) command earlier. The "A" (Alphabetize or Arrange or Alpha sort) toggles the way in which the files are sorted, namely alphabetically by the file name or by the file type. The "S" (Status) command prompts you for a disk drive letter and then tells you the amount of space remaining on that disk. The "E" command (refresh scrEEn -- I know that's stretching things, but "R" was already used) redraws the screen. You might think that this would never be needed, but there are two circumstances in which it comes in very handy. One is when ZFILER is being used on a remote system. It is trueŠthat very few RASs make ZFILER available, but I do on Z-Node #3. If you get some line noise, the screen can become garbled. Then the "E" key can be used to draw a fresh screen. The other circumstance in which the "E" command saves the day is with Backgrounder-ii if you do not have a screen driver (I don't for my Concept 108 terminal -- never got around to writing one, partly because all the programs I use frequently have a redraw key like this one). I simply define a BGii key macro specifying "E" as the "redraw" key, save the key definitions to ZFILER.BG, and attach that definition to ZF.COM. Then whenever I swap tasks back into ZFILER, BGii simulates my pressing the "E" key, and the screen is redrawn. This often gives a faster screen refresh than one gets with a full-fledged screen driver. The "H" (Help) command generates a macro command to invoke the Z-System HELP facility. To tell the truth, I have not used this and don't even remember precisely what it does. I would have to look at the source code. The "Z" (Z-system) command prompts you for a command, and whatever you enter is passed on to the Z-System multiple command line buffer for execution. When that command line is complete, ZFILER is reinvoked automatically. When you use the "Z" command, you will normally be logged into the directory that is currently displayed. However, this will not always be possible. ZFILER allows you to select directories with user numbers from 0 to 31. Unless you are using a version of ZCPR33 or ZCPR34 with the HIGHUSER option enabled, you cannot log into user areas above 15. In that case ZFILER will put you in the directory your were in when you invoked ZFILER. In any case, the command prompt will indicate the directory from which your command line will be executed. Since commands you run using the "Z" function may put some information on the screen that you would not want ZFILER to obliterate immediately, there is a flag set that signals ZFILER to prompt you and to wait for you to press a key before putting up its display. Here is a tip for advanced users. If you enter your command line with one or more leading spaces, this shell-wait flag will not be set, and ZFILER will return without your having to press a key. The leading spaces are stripped from the command line before it is passed to the command processor. This means that you cannot use a leading space to force invocation of the extended command processor (ECP); you have to use the slash prefix instead. A space and a slash will force invocation of the ECP and will disable the shell-wait flag. The final command in class A3 is the "O" (Options) command. It is a complex topic, and I will leave it for next time. If you can't wait until then, experiment with it. It should not be able to do any harm to your system. Single-File Built-In Functions Now let's discuss the commands in class A1, the built-in commands that act on the pointed-to file. These are invoked by pressing one of the following keys, whose meaning is indicated in parentheses: C (Copy), M (Move), D (Delete), R (Rename), V (View), P (Print), F (File size), T (Tag),Šand U (Untag). Some of these are self-explanatory, and I will not discuss them. The "C" command copies a file to another directory under the same name; it does not allow one to give a new name for the destination file (however, you can do that with a macro command). The "M" command does not really move a file; it copies the file and then, if the copy was successful, deletes the original file. It is really a combination of "C" and "D". Moving a file this way is inefficient if the destination directory is on the same drive as the source file. A macro command that invokes an ARUNZ alias can get around this limitation (and almost all other ZFILER limitations). The tag and untag commands are used to select a group of files on which operations can be performed. Tagged files are indicated in two ways. A special character ("#") is placed after the file name in the display, and, if the terminal supports video highlighting, the file is highlighted. Two related commands are W (Wild tag) and Y (Yank back?). "W" allows you to tag or untag groups of files designated by an ambiguous file spec. After tagged files are operated on by the built-in group commands described below, the tag marker "#" is changed to "'" (a soft tag). The "Y" command changes the soft tags back into hard tags so that further group operations can be performed on those files. Built-In Group Commands Group commands are initiated by pressing the "G" (Group) key. The command prompt at the bottom of the screen changes to Command? (/=Help, X=Quit) Group: (A,C,D,F,M,P,R,T,U,V) For now we will consider only the built-in group functions (class A2) and will take up group macro commands (class B2) next time. Except for the four functions described below, the letters invoke the same action as the individual command corresponding to that letter, but the function is performed on all the tagged files. We will not discuss those further. Note in particular that the keys "A" and "R", however, have a group function that is completely different from the individual function. The "U" and "T" group functions do not act on the tagged files; they change the tagging. The former untags all files; the latter tags them all. The "R" group function is another one that does not, strictly speaking, act on the tagged files. It reverses the tags, tagging the files that had been untagged and untagging the ones that had been tagged. This can be very handy in several circumstances. For example, you might want to copy all the files except two. It is easier to tag those two and then to reverse the tags. As another example, you might want to copy some of the displayed files to one diskette and the others to a second diskette. I do this frequently. I begin by tagging the ones to go to the first diskette. Then I group copy ("GC") them to the destination diskette. Next, I yank back the tags using the "Y" command and then reverse the tags with "GR". Now I can group copy the rest to the second diskette. Š The "A" (Archive) group command is very handy for automating backups. When it is entered, the tags are removed from any tagged file whose archive flag is set. As a result, only files that have been modified since the flag was last set will remain tagged. In addition, the "A" group command automatically initiates a group copy operation but with one special feature. After the file has been copied successfully, the archive flag on the source file is set to indicate that the file has been backed up. Under later versions of VFILER, the group "A" command automatically tagged all unarchived files; under ZFILER it untags the archived ones. This difference is very important. With VFILER, you were forced to back up all the files selected by the VFILER file mask. Under ZFILER you can select the files that will be candidates for backing up. If you want the achieve the same function as under VFILER, just tag all the files first with "GT" and then archive them with "GA". On the other hand, if you want to exlude BAK files from the backup, you can "GT" all files, untag the "*.BAK" files using the "W" command, and then use the "GA" command. After you enter the command "GA", you will be prompted for a destination directory. You do not have to supply one! If you simply enter a carriage return, the copy operation will be skipped, and you will be left with tags on the files that need to be backed up. You can then use a macro function to back them up in a specialized way, such as crunching (compressing) them to the backup disk (instead of copying them as they are) or putting them into a library on the backup diskette. Next time we will discuss the macro techniques required to do this. ZFILER, Installment 2 ===================== Last time we covered most of the built-in functions and had left the macro commands for this time. One built-in function was also deferred, the option command "O", and we will take up that subject first. The Option Command When the option command letter "O" is pressed, a special options screen is displayed. Eleven operating characteristics can be changed from a menu with the following appearance (approximately): A. single replace query Y B. group replace query Y C. archive replace query N D. verify query Y E. verify default Y F. suppress SYS files Y G. sort by file name N H. set copied file attributes Y I. use dest file attributes Y J. archive destination Y K. search path for CMD file N We will explain the meaning of each of these options in a moment. First aŠfew words about the mechanics. While the options menu is displayed, pressing the index letter at the left will cause the setting of the corresponding option to be toggled, and the new state will be shown in the column at the right. The listing above shows the initial state of the options in my personal version of ZFILER. When you are finished toggling options, just press carriage return to return to the main ZFILER menu. These option settings are stored in the ZFILER shell stack entry and will thus continue in effect through all ZFILER operations until the command "X" is used to terminate the shell. The first three options concern how ZFILER responds when copying (or moving) files and a file of the same name already exists in the destination directory. Item A applies when individual files are copied (commands "C" and "M"); item B applies when a group copy is performed (commands "GC" and "GM"); and item C applies when performing an archiving operation (command "GA"). If the option is "YES", then ZFILER will prompt one before existing files are erased and give one the chance to cancel the operation for that file, leaving the existing file intact. If the option is toggled to "NO", then existing files will be overwritten without even a message. The next two options affect the verification of the copied file in the destination directory. Item D determines whether or not the user will be asked about verification. If this option is set to "N", then the state of option E will determine whether or not verification is performed on file copies. If this option is set to "Y", then before each copy, move, group copy, or group move, ZFILER will put up the prompt "Verify (Y/N)?". The next two options affect the way files are displayed on the screen. If item F is set to "Y", then files with the "system" or SYS attribute will be suppressed, that is, not included among the selected files on which ZFILER acts. This is a reasonable choice for this option, since the most common use of the SYS attribute is to make the files disappear from consideration during file maintenance and display operations. Item G on the options menu determines whether files are sorted first by name and then by type or vice versa. Changing this option is presently equivalent to the "A" command from the main ZFILER command menu. The next three options concern how file attributes are treated when files are copied. One possibility is to create new files with a clean slate of attributes (that is, all attributes reset: not read-only, not SYS, not archived). This is what will happen when option H is set to "N" (but note option J, which may override this). When the attributes of the destination file are to be set, they can be set in two possible ways. If a file of the same name existed in the destination directory, then its file attributes could be used for the copy that replaces it. This is what will be done if option I is set to "Y". If option I is set to "N" or if there was no matching file in the destination directory, then the attributes will be set to match those of the source file. Option J can set a special override for the archive or ARC attribute. If the option is set to "N", then the ARC attribute is treated just like the other attributes according to options H and I. If option J is set to YES, then the destination file always has its ARC attribute set. There was at one time a great deal of controversy over the way the ARCŠattribute is handled under ZFILER. At one time it was always reset, so that the destination file would be marked as not backed up. Another school of thought asserted that, on the contrary, the file was backed up, since there was a copy of it on the source disk from which the file was copied. That latter argument made considerable sense in the case of copying files from a master disk to a RAM disk before a work session. Here it was certainly important to start with all files marked with the ARC attribute so that one could easily tell at the end of the session which files had been modified so that they could be copied back to the permanent storage medium. All in all, I never understood this controversy. Both approaches clearly have merit, and since ZFILER supports both, I saw no reason for all the argument. In a future version of ZFILER, I think I would like to add a flag word that would indicate which drives should automatically set the ARC flag when the J option is set to YES. That way, the option could be made to apply to RAM drives only. The final item on the option menu, option K, determines how the macro command file ZFILER.CMD (see discussion below) will be located. There are two choices. If option K is set to YES, then ZFILER will look for it first in the currently displayed directory and then along the entire ZCPR3 search path. This option is useful if one wants to have different macro command files that apply to specific directory areas. Alternatively, if option K is set to NO, then ZFILER locates the CMD file without using the path. Depending on how ZFILER is configured (this will be discussed another time), the file will be sought either in the root directory of the path (the last directory specified on the search path) or in a specific drive/user area codeä intï ZF.COM® Thió alternativå resultó iî fasteò operation¬ especiallù iæ thå specifieä directorù resideó oî á RAÍ disk. The options controlled by the option menu can also be permanently changed in the ZFILER program file using a patching utility like ZPATCH. In the first page of the file, you will see the ascii string "OPT:". The eleven bytes following this string contain the startup values for the eleven options. Patch a byte to 00 for NO or FF for YES. ZFILER Macros Although ZFILER can accomplish many tasks using its built-in functions, its real power comes from the macro facility, which allows it to be extended to include any functions that can be performed using combinations of other programs. This is where ZFILER really makes use of its power as a shell. First I will describe how the macro facility is used, and then I will describe how the user defines the macro functions. As with the built-in functions, macro functions can operate either on single files or on groups of files. The single-file macro facility is well developed and was already present in nearly the same form in VFILER; the group macro facility is new with ZFILER and has not been fully developed yet. Invoking Macros One way to initiate a macro operation on the pointed-to file is to press the macro invocation key, which is normally the escape key. A prompt ofŠ"Macro:" will appear after the normal ZFILER command prompt. At this point you have several choices. If you know the key corresponding to the macro you want to run, then you can simply press that key. ZFILER will then construct a command line and pass it on to the command processor for execution. If ZFILER is configured for instant macro operation (it generally is), then macros associated with the number keys "0" through "9" can be initiated without the macro invocation key; the number key entered alone at the main ZFILER command prompt will generate the macro function. If you press the macro invocation key a second time, a user-created help screen will be displayed. This screen generally lists the available macro functions. You can now press the key for the desired function, or you can press carriage return to cancel the macro operation and return to the main ZFILER menu. The help menu screen will also be displayed if you press the "#" key. This is a holdover from VFILER and arises in part because of the structure of the file in which the macros are defined (more on this shortly). Group macros are invoked in a similar way from the group function command line. After you have tagged a group of files, press the "G" key to enter group mode. The prompt will list only the built-in group functions, but if you press the macro invocation key, you can proceed as described above for single-file macro operations, except that the macro function will be performed on each of the tagged files. The group macro facility works a little differently than the single-file macro facility. Since the command line would generally not be long enough to contain the commands for all the tagged files, the group macro facility works by writing out a batch file for processing by ZEX or SUBMIT. In this way there is virtually no limit to the number of files on which group macros can operate. There are many configurable options (described below) that are associated with the group macro operation. These include the name of the ZEX or SUB batch file, the directory to which it is written, and the command line that ZFILER generates to initiate the batch operation. The NZ-COM version of ZFILER uses a file called ZFILER.ZEX and the command line "ZEX ZFILER". The Z3PLUS version, under which ZEX will not run, uses a file called ZFILER.SUB and a command line of "SUBMIT ZFILER". Since macros (and the main menu "Z" function) work by passing commands to the command processor, file tags will be lost in the process, and when ZFILER resumes operation, it starts afresh. In a future version of ZFILER, I hope to preserve the tag information by having it optionally written to a temporary file (the shell stack entry is far too small) and read back in when ZFILER resumes. Defining Macros -- The CMD File Now let's learn how to define the macro functions we want. As I indicated earlier, the macros are defined in a file called ZFILER.CMD (the ZFILER ComManD file). In the version of ZFILER distributed with NZ-COM and Z3PLUS, the CMD file is searched for in the root directory of the ZCPR3 command search path. As described earlier, the option menu allows theŠentire path to be used. There are also some additional configurable options that will be discussed another time. You must be sure to put your ZFILER.CMD file in the appropriate directory. If the file cannot be located, you will still get the macro prompt, but, after you have specified a macro key, the error message "ZFILER.CMD NOT Found" will be displayed. The ZFILER.CMD file is an ordinary text file that you can create with any editor or wordprocessor that can make plain ascii files (WordStar in nondocument mode, for example). The CMD file has two parts. The first part contains the macro command definitions; the second contains the help screen (described earlier). In the first part of the CMD file, each line defines a macro. The character in the first column is the key associated with that definition (case does not matter). Macros can be associated with the 10 number keys, 26 letter keys, and all printable special characters except for "#" (explained below). The space character and all control characters are not allowed. Owing to an oversight, the rubout character can be associated with a macro! After the character that names the macro there can be any number of blanks (including zero). If the first non-blank character is "!", then the "strike any key" (shell-wait) prompt will appear before ZFILER puts up the file display after a macro command is run. This should be used whenever the macro will leave information on the screen that you will want to read. After the "!" there can again be any number of spaces. Any remaining text on the line is taken as the script for the macro command. The second part of the CMD file starts when a "#" character is found in the first column (hence the exclusion of that character as a macro name). Once that character appears, all remaining text, including text on the line, will be used as the help screen. Since ZFILER will add some information to the display (the name of the pointed-to file and a prompt), you will generally want to keep the help screen to no more than 20 lines, including an extra blank line at the end for spacing. With some experimentation you will get the hang of designing this screen. Macro Scripts ZFILER macro scripts are similar to those in ARUNZ and in the other menu shells (MENU, VMENU, FMANAGER) in that parameter expressions can appear. The critical parameters -- the ones that implement functions that cannot be achieved any other way -- are those that convey information about the directory currently displayed by ZFILER and about the pointed-to file. Parameters consist of a "$" character followed by one of the characters listed below. User prompt parameters ' User input prompt " User input prompt Parameters for directories - currently displayed directory Š C DIR form D Drive letter U User number - home directory (from which ZFILER was invoked) H DU form R Home DIR Parameters for pointed-to file P Full information (DU:FN.FT) F File name (FN.FT) N File name only T File type only Special parameters ! GO substitution indicator $ The dollar character The parameters are listed in a special order above, and we will explain that later. First we will just present the meaning for each parameter. The parameter expressions $" and $' are used to display a prompt message to the user and to read in a response string. Single and double quotes are equivalent. Once the prompt parameter has been detected, all subsequent characters up to one of the quote characters are displayed as the user prompt. Thus, if I am not mistaken, there is presently no way to put either quote character into the prompt. The end of the line or the end of the file will also terminate the prompt. No special character interpretation is performed while expanding the prompt. If you want to make fancy screens, you can include escape sequences and some control characters (obviously carriage return won't work). In the future, ZFILER should be enhanced to provide a means to generate all control characters, to allow special characters to invoke screen functions based on the current terminal definition, and to expand directory and file parameters in the prompt. Now for the directory parameters. Parameters C, D, and U return information about the currently displayed directory, while H and R return information about the home directory, the one from which ZFILER was originally invoked. PLEASE NOTE: macros always operate from the home directory. The reason for this is that ZFILER can display directories with user numbers higher than 15 even when it is not possible to log into these areas. If you want to operate in the displayed directory, then your script must include an explicit directory-change command of the form "$D$U:" at the beginning (or "$C:" if your system requires the use of named directories) and a command of the form "$H:" (or "$R:") at the end. One special note about the parameters that return directory names. If the directory has no name, then the string "NONAME" is returned. This will presumably not match any actual name and will lead, one hopes, to a benign error condition. These parameters are included only for systems that do not allow directories to be indicated using the DU form (I hope that few if anyŠsystems are set up this way). Now we come to the four file name parameters. They allow us to generate easily the complete file specification or any part of it. Note that "$F" is not quite the same as "$N.$T". The latter always contains a dot; the former does not if the file has no file type. Finally, we have two special parameters. "$$" is included to allow a dollar sign character to be entered into the script. "$!" is a control parameter that is used only when a group macro is executed. If it is placed immediately before a token (string of contiguous characters), then that token will be replaced by the string "GO" on all but the first expansion of the script. This allows group macro scripts to operate faster by avoiding repetitive loading of a COM file. It must be used with great care and consideration, however, for reasons that I will not go into here. Rules for Script Expansion ZFILER follows a specific sequence of steps when expanding a script, one that gives it a special feature that, I would guess, few users are aware of. The first step in the expansion is to process only the user-input prompt parameters, substituting for the prompt whatever the user entered in response. This results in a modified script that is then processed by the second step in the expansion. Because the expansion is handled this way, the user input can include ZFILER script parameters! Thus the script can be used to write a script. You will see an example of this later. The second step in the expansion is to substitute values for the directory parameters, which are a kind of constant. They do not change as a function of the pointed-to file. Finally, in a third step, the remaining parameters are expanded. For group macros, this final step in the expansion is repeated for each of the tagged files. The file parameters are expanded differently for each file, and, starting with the second tagged file, the "$!" parameter causes "GO" substitution. Macro Examples Listing 3 shows an example of a ZFILER.CMD file, one designed to illustrate some techniques of macro writing. While writing this article, I discovered that one can include blank lines as shown to make the CMD file easier to read. The help screen part of the listing is taken from my personal script file (which, I have to confess, I have not really worked very hard at). The macro definition part of the listing includes only a few of the definitions. The macro "Q" is included to illustrate a very simple, but useful, type of macro. It invokes the very powerful file typing program QL (quick look) on the pointed-to file. This is handy when you want more powerful viewing capability than that offered by the built-in "V" command. QL can handle crunched files and libraries, and it can display text or hex forward or backward. Macro "U" uncompresses a file. It illustrates a more complex script thatŠinvolves flow control and parameters that extract individual components of the pointed-to file name. It tests the file type to see if the middle letter is "Q" or "Z". In the former case, it unsqueezes the file; in the latter, it uncrunches it. The uncompressed file it put into the source file's directory. Macros S, K, and B illustrate the use of input prompting. The first one allows the user to specify the file attributes to be set. Note that the prompt includes a helpful reminder of the syntax required by SFA. Macro K crunches files to a user-specified destination. It also illustrates how one logs into the currently displayed directory. I do this here so that a null answer to the prompt (i.e., just a carriage return) will result in the crunched files being placed in the currently displayed directory rather than in the home directory, as would otherwise be the case (since that is where the macro runs from, remember). As a result, however, this macro will not operate properly in user areas above 15 under BGii or versions of the command processor that do not allow logging into high user areas. Macro B performs a slightly more complex function. It not only compresses the pointed-to file to a specified destination directory, but it then marks the source file as having been backed up. A combination of the group archive built-in command (to tag files that need backing up) and a group macro B (to perform the backup) gives the ZFILER user a way to back up files in crunched form on the backup disk. Macro M is included to show that a ZFILER macro, when it needs to do something more complex than it is capable of doing all by itself, can pass the task to an ARUNZ alias. The MOVE alias first determines whether the source and destination are on the same drive. In that case, MOVE.COM is used to perform the move. Otherwise, the source file is copied to the destination and then deleted. What we have, therefore, is a MOVE command that frees the user of the responsibility of worrying about which drives are involved -- another example of how Z-System can free you from considerations that need not concern you, that do not require human intelligence to decide. The final three macro examples are execution macros. Macro X causes the pointed-to file to be executed. A more sophisticated version might check to make sure that the file type is COM. I opted for the flexibility of pointing, for example, to PROGRAM.Z80 and having PROGRAM.COM run. If there is no COM file with a matching name, the error handler will take care of things. You will note the leading colon before the "$n" parameter. It makes sure that the current directory is searched even if it is not on the path. Prompted input is used to allow a command tail to be included. The Z macro performs a user-specified function on the pointed-to file. Two separate user prompts allow both the command and a command tail to be given. For example, if you wanted to squeeze the file to A0:, you would enter "SQ" in response to the first prompt and "A0:" in response to the second. The 0 macro illustrates how the response to a prompt can be used as a ZFILER script. This macro takes care of all those functions we forgot to include in ZFILER.CMD. The whole macro is just prompted input, and whateverŠwe answer will be run as a script. I use this function so often that I put it on a number key so that it can be invoked with a single key rather than the usual pair. Also, as you may have noticed, I include in the macro help screen a list of the parameters that can be used. The only real limitation of this macro-to-write-a-macro approach is that prompted input cannot be included in the response. As I write this, however, it occurs to me that this limitation could be overcome by recursively parsing the prompt parameters until none remain, and only then going on to the subsequent macro expansion steps. Well, I was going to discuss patching and configuring ZFILER, but this article is already too long, so that will just have to wait for another time. I hope that this article will help you get more out of ZFILER. See you in the next issue! LISTINÇ 3 --------- Q ql $p U ! if $t=?q?;$!sys:uf $p $d$u:;else;$!sys:uncr $p $d$u:;fi S ! $!sfa $p $" SFA Options (/o,o.. o=ARC,-ARC,R/O,R/W,SYS,DIR): " K ! $d$u:;$!crunch $f $"Destination directory (DU:) -- ";$h: B $d$u:;crunch $f $"Destination directory (DU:) -- ";sfa $f /arc;$h: M ! /move $p $"Destination directory for move: " X ! $d$u:;:$n $" Command Tail: ";$h: Z ! $d$u:;$" Command to perform on file: " $f $" Tail: ";$h: 0 ! $"Enter ZFILER macro script: " # SAMPLE ZFILER MACROS FOR TCJ 0. on-line macro A. set Archive bit N. NULU 1. LPUT B. Backup (cr/sfa) O. 2. Z80ASM to COM C. CRC P. Protect 3. Z80ASM to REL D. Date display Q. QL 4. Compare Files E. Edit R. 5. F. S. SFA 6. G. T. Type 7. H. U. Uncompress 8. I. V. VLU 9. J. W. K. Krunch X. eXecute L. LDIR Y. M. Move Z. run command $! ZEX 'GO' $D DRIVE $P DU:FN.FT $F FN.FT $".." PROMPT $U USER $N FN $T FT $'..' PROMPT $H HOME