Home > Progamming > Programming Tips

 

 

I collected these tips from the Nota Bene list between spring 1999 and the end of March 2000. They are very roughly in order of collection. They include the name and usually the email address of the person who posted them. From early 2000 I began keeping the date of posting as well.

These tips presumably work for the contributor, but bear in mind that they may not work with all operating systems (Windows 3.x/95/98/NT, etc.) and hardware configurations.

Mary Bernard

April 2000

 

Download a print-friendly NBWin copy of this FAQ here (v. 1.0, April 2000, 9k).

 



BX explained / When to use parentheses in programming for NB5


Does any one know why or when parenthesis are required around what looks like a standard NB command text in these programs? There was no such need in the DOS XPL.

BX is a new facility, which appears in Signature and all of its descendants (Xy4-DOS, XyWin, NBWin, SmartWords). BX means Blind EXecute. It enables Editor to issue commands without (usually) disturbing the command line, at much greater speed than via the command line. Moreover, commands are no longer limited in length to the size or space of the command line (80 chars in DOS, more in the GUI versions). Any command formerly issued with "BC commandXC " can also be issued with BX, but BX is specifically for XPL programming. The form of a BX command is:

BX commandQ2

An abbreviated form is:

BX (command)

Most XPL programmers have realized from experience using these two forms that the parenthetic form is not 100% reliable, and therefore they generally use BX ...Q2 . For one thing, if using parentheses the command may not contain either the "(" or ")" character, and very frequently these two chars do creep into commands if the content is only known at runtime, e.g. in something like "BX <PV01>Q2 " (where Save/Get 01 is constructed from user input or some other variable). It is possible also that <PV01> (to use that number just as an example) might contain a function or a three-byte character, and that this 3-byter could itself contain a parenthesis in one of its three underlying bytes (even though it would never display in NB as such). That could cause the command, and the routine that runs it, to crash. And then there are fudgy situations where BX () just crashes for no discernable reason, whereas BX ...Q2 executes.

Other commands, such as JM ...Q2 can also be stated parenthetically, as JM (framename), but again, for the same reasons, it is always best to use the JM ...Q2 form. Curiously, the programmers at both NotaBene and at XyQuest/TTG are very inconsistent in their approach, and seem to use both forms almost indiscriminately, as if by personal preference.

- - - - - - - - -

BX was one of the many new XPL functions introduced with XyWrite 4 (or, actually, its predecessor, Signature) back in the early '90s. BX stands for Blind eXecute -- meaning that it executes a command (any command) without first placing it on the command line, and so without erasing whatever happens already to be there. Besides CMline preservation, the welcome effects of using BX instead of BC . . XC include much-increased speed (especially in programs that execute many commands), and a "calmer" screen (because the command line isn't constantly being blanked and refreshed).

Re: the question about the parentheses, the basic syntax is BX (command), where "command" is any legal NB/Xy/SmartWords command, including arguments. So, BX (new), or BX (ne), opens a new Untitled file, while BX (ne MYFILE.TXT) opens a new file so named. You can substitute square brackets [] or curly braces {} with commands which themselves include parens. For example, to search for a single close paren: BX [se )].

There's an alternate Blind Execute usage -- the preferred usage, actually -- whereby the command is sandwiched between funcs BX and Q2 (the latter not to be confused with the spell-check function of identical name). That is: BX commandQ2 . This usage is preferred because it overcomes a limit (I don't remember off-hand what it is) on the length of the command-to-be-executed and, more important, because in rare but critical situations BX (command) has been known to fail, whereas BX commandQ2 always succeeds.



Symbol * and its use


[as in the following:    ;*; BX (new)    ...]

The symbol ;*; is another useful addition to XPL: it causes everything following it, up to and including the next carriage return, to be treated as a comment (i.e., not executed). With it, comments and white space can be added liberally, for clarity and readability, without slowing programs down. (Amazingly for an interpreted language like XPL, there's no performance hit at all.)



GC command


The GC command, which stands for general citation, is placed in the file when:

  1. an academic manual of style is imposed on the file, or
  2. in citing references in a non-academically stylized paper, Ibidem places a gc once the format for citations is chosen.



Using XYWrite programs in NB5


Our colleagues on the XyWrite side of things have been very busy over the years getting under the hood of their word processor of choice, and the results are a rich collection of XPL programs, many of which are available from a web site maintained by Robert Holmgren. Many such programs, particularly those developed by Robert and Carl Distefano (currently web master of the XyWrite discussion list, xywrite@ccat.sas.upenn.edu) are collected in a single help frame that can be loaded into XyWrite DOS and XyWrite for Windows at startup, called XyWWWeb.U2. It turns out that this collection can be loaded in NBWrite as well and that many of the routines found in it run perfectly well in NBWrite. The following are the steps to take to get XyWWWeb.U2 frames mounted and (often) working under NBWin.

  1. Download the package from http://www.serve.com/xywwweb/
  2. Unzip package and place the XyWWWeb.U2 file in the directory of your choice (for example, C:\NBWin\users\default\).
  3. Place the following commands in NBSTART.INT found in your NBWin directory:
       BX load c:\nbwin\users\default\xywwweb.u2Q2
      BX load c:\nbwin\users\default\nb.kbdQ2

    [Substitute your path for mine, if different. NOTE that BX and Q2 are functions that are entered by typing pfunc bx<CR> and pfunc q2<CR> on the command line].
  4. Establish a XyWWWeb helpkey by entering the following into your keyboard file (where nn=the key of your choice; I used CTRL-keypad5 which appears not to be assigned in NBWin and has scan code of 76):
       nn=NOXHJM,2,.,P,r,s,C,M,l,i,n,e,Q2
    [In this case, Q2 is entered as plain text, not as a function].
  5. Exit NBWin and restart, and try out. For example, entering SCANCODE on the command and pressing your new helpkey will reveal the keyboard scan code of any keys you press until you issue ESC to cancel the program.

Not all XPL programs written for XyDOS (ver. 4) or XyWin will run under NBWin, but many in fact do. If you run across an XPL program written for XyWrite, usually having an .PM instead of a .RUN suffix, be sure you load it as an NBWin file if you try to edit it at all (to insert a path, for example). If it is loaded as an XyWrite file, some translation of the program apparently takes place and the result usually will not work.



Programming mode, a XYWrite approach


Has anyone made the programming mode in NB Win work?

Sure, although not using func TS like you're trying to do. Func TS always struck me as too hot to handle. What I'd do is find out whether func RK (Record Keystrokes) is assigned in your NB keyboard (I use my Xy4-DOS keyboard, so don't know); if it isn't there, add it somewhere. It's a toggle func, on/off. The first time you hit it, it starts recording your keystrokes; the second time it stops recording. (You can take a quick look at the contents -- the first 80 bytes anyway -- to make sure you were successful, by polling (on the command line) an internal (and unfortunately inaccessible) Save/Get called <VA@*11>, thus:

va/nv @*11<cr>

To get your keystroke macro into useful form, command:

LDRK x<cr>

where "x" is an ordinary Save/Get 0-9, A-Z, or a special programming S/G &0-&9, &A-&Z. If you use an ordinary S/G, and they're assigned in your KBD file -- again, I don't know, assignments should look like @A, @B, etc. -- then you just hit that keystroke to run the macro. This is the easiest way to use "programming mode" (TS was an old Xy3+ concept, superseded about 10-12 years ago).



Putting in a macro


Does anyone know how to place in a NBwin macro file? I tried using the Keystroke recording function and the saverk function to save it to a file, but I failed to make a macro that would find and replace it. Nor does the scroll lock method seem to work.

Keep Ctr+Shift pressed and type the keys 1 and 0 above the alpha keys (NOT the numpad keys) and release. This puts an ASCII 10 in the file, a linefeed strictly speaking, but in xpl macro searches it looks for paragraph end markers or .

This seems to be the general way of inserting characters whose ASCII decimal code you know: NOT alt-shift as in NB4 but ctrl-shift, NOT the numeric pad number keys as in NB4 (or DOS in general) but the number keys above the alpha keys.



Function &X


What does &X do?

I'm not sure, but I have found that it seems to work almost interchangeably with BX or BC, executing the command that follows. I have found that by using this wherever NBWin uses it, I have fewer bugs in my heavily customized Xywrite 3.55 keyboard file (which I am using in NBWIN). I therefore suspect that &X is related to a NBWin Xpl program, which does other functions as well as executing a command.

- - - - - - - - -

If you look in the main directory you'll see a bunch of files called nbmain-x/a/s/etc.aux -- these appear to be collections of xpl routines. In the users\default directory, in nb.ini, which is clearly the startup file, you'll see at the end a series of ldpm commands, putting these on the secondary phrase keys called by the function: &x,&a,&s, etc. (the primary phrase keys are @a, @b, etc. which correspond to Nbdos alt- a, alt-b, etc. and are now called glossary keys on Alt-Shift). It would appear from the keyboard table that &x,y,z calls the program loaded as on x, with the argument yz; the program is nbmain-x.aux and it reads the argument with the au function and branches to the appropriate label. If you want to read the .aux files you might have to call them in nb4 in show codes, and remove the la2 delta at the top, which is I guess a trick for obscuring them.



NEP and CAP may be unnecessary in NB5


If you wanted to use program mode in NB4, you had to open or create the program with 'cap' or 'nep'. This isn't true in NB5. If programming mode is toggled on, it inserts program codes into files that have been opened with the ordinary 'ca' or 'ne'. There may be circumstances in which 'cap' and 'nep' are necessary in NB5, but I haven't yet come across them. It's a useful simplification.



Blind Execution of Commands


Instead of "BC command arg(s)XC " to execute a command, use "BX command arg(s)Q2 ". There are several important advantages. Any existing command line is preserved. The command to be executed is no longer limited by the length of the command line. And, because the command line isn't continually being blanked and refreshed, programs execute faster and with a much cleaner display.



SEarching in NB5


SEarching in NB5 is more powerful. To search for a carriage return (as you found out at the expense of a late winter's morning), you simply put it in the search statement: BX se / /Q2 , though for readability it's preferable to use the carriage-return "wildcard" character, produced by executing func WC. (Note that you don't put "WC " in the search command; you execute func WC to get the desired wildcard character.)



Searching for command brackets


To search for the Ascii-174 and -175 command delimiters, you can, again, insert the characters themselves, but it's not advisable due to the likelihood of unbalanced guillemets, which generate errors. Instead, use the guillemet wildcards, generated by executing func << (two "less than's") and func >> (two "greater than's") at the desired cursor location.



Searching--switches


The SEarch command has a number of new and useful switches.

  • SE/F |string| puts the cursor on the first letter of the found string.
  • SE/W |string| finds string only if it's a self-contained word.
  • SE/S |string| limits the search to selected text (DeFined block). If the cursor is outside the block, the block is searched from beginning to end. If the cursor is inside, the block is searched from cursor location to the end of the block.
  • SE/3 |string| finds the third instance of string (obviously, you can substitute any number).

All of these switches, except /F, apply as well to CHange and Change-Verify commands. (CH and CI now work identically, by the way.)



Searching - wildcards


There are several new search wildcards, including one that enables searches for this OR that. The OR wildcard is produced by executing func NN, then hitting "O". Keyboard file assignment: nn=NN,O



Commenting a program


The comment symbol ;*; allows liberal inclusion of comments in programs without speed penalty. The comment extends from the comment symbol to the next carriage return, thus:

   <SV01,A rolling stone>;*; First half of proverb



Appending to a phrase in programs in NB5


It's unnecessary to save text to a phrase in order to add it to an existing phrase. Simply "quote" the additional text. Thus:

   <SX01,<IS01>+" gathers no moss.">;*; Full proverb



Echo phrase to prompt line


You can echo the contents of a phrase to the PRompt line:

   <PR@01>;*; Proverb is displayed on PRompt line

Note: Default MB must be set to 0. If default MB=1, the contents will display in a Windows message box which will persist on the screen until you press Enter or click on "OK". This causes problems with programs that loop repeatedly through PRompt statements.



Prompt can mix text and phrase number


A PRompt may consist of text and a phrase number, as long as the phrase number comes last:

   <PRHere is the proverb: @01>;*; Proverb with prefatory remark



Manipulate variables and values directly


System VAriables and VAlues can be manipulated directly. It's no longer necessary to save the VA to a phrase:

   <IF<VA$WS>==0><PRNo file is open><EX><EI>;*; Test for open file



New extensions to VA operator


There are several extremely important extensions to the VA operator:

@siz(<IS01>) to get the length of a phrase is passe. Use <VA|01>.

@siz(<IS01>) crashes if phrase 01 is uninitialized; <VA|01> doesn't; rather, it returns a value of -1 (useful information).

<VA.01> tells you whether 01 contains a number (integer) or a string. 1=number; 0=string

<VA!01> provides important information about the status of phrase 01. If:

   VA!01=0,   phrase 01 contains a string
   VA!01=2,   phrase 01 contains SUbroutine
   VA!01=4,   phrase 01 contains a numeric expression
   VA!01=16,  phrase 01 evaluates to FALSE
   VA!01=24,  phrase 01 evaluates to TRUE
   VA!01=255, phrase 01 is not initialized

<VA@01> returns the first 77 characters of phrase 01, the whole phrase if the length is 77 or less. An extension to VA@ allows easy extraction of segments delimited by a separator. Suppose this:

   <SV01,Spring;Summer;Fall;Winter>;*; Data

Then <VA@01;1>=="Spring", <VA@01;2>=="Summer", etc.



Containment operator (replaces epsilon)


There's a new Ascii-240 containment operator, which tersely reports whether one string "contains" another. (The operator is the Ascii- 240 character itself, not the number in curly braces.) For example:

<IF"Spring"{240}"pr"><PRYes><EX><EI><PRNo><EX>;*; Reports "Yes"
;*;
<IF"Spring"{240}"Pr"><PRYes><EX><EI><PRNo><EX>;*; Reports "No"

The epsilon containment operator works as before.



Time your programs!


You can now time your programs. Func ZT ("Zero Time") resets the timer to 0. The Elapsed Time is reported by <VA$ET>. Here's how you would time how long it takes to count to 10,000:

<SX01,0>ZT ;*; Initialize 01 and reset timer
;*;
<LBa><IF<PV01><10000><SX01,<PV01>+1><GLa><EI>;*; Count up
;*;
<SX01,"Done - Elapsed time: "+<VA$ET>><PR@01><EX>;*; Report elapsed time



Count Up operator


There's a nifty Count Up operator that makes it easy to execute a segment of code a specified number of times. Using it, the above code [in Time your programs!] can be rewritten like this:

<SX01,10000>ZT <CUa,01>NO <LBa>;*; Count Up
;*;
<SX01,"Done - Elapsed time: "+<VA$ET>><PR@01><EX>;*; Report elapsed time

In the first line, everything between the <CU> statement and LaBel "a" (<LBa>) -- in this case, a simple func NO (No Operation) -- is executed the number of times stated in phrase 01. CU requires two elements, a delimiting LaBel name and a phrase which must contain the desired number of repetitions. Note how compact the CU formulation is. Also, if you translate the examples into live code and run them, you'll see that CU is significantly faster (on my machine, by a factor of 135%).



Using the XyWWWeb Jumbo U2


There are scores of new system VAriables which are highly useful in XPL. With the XyWWWeb Jumbo U2 installed, you have easy access to information about them with the command TABLE VAR<Helpkey>. Similarly, the many new functions can be viewed with TABLE FUNC<Helpkey>. (Helpkey is a key assignment that enables access to XyWWWeb programs and help facilities. Details are in the documentation.)



Auto turnoff of error suppression


Finally, if you activate error suppression in a program (BX es 1Q2 ), it's no longer necessary to turn it off at the end. This happens automatically.



GT


GT can be used to put text on the command line as well as in text. Thus,

   <SV01,Hello, world!>BC <GT01><EX>;*; Put to command line
   <SV01,Hello, world!>GT <GT01><EX>;*; Put in text

In Xy3 (possibly also NB3 and 4), PV was required to put text on the CMline.



Search for command codes


You can search for a particular command code by striking your Pfunc key (Ctrl ;) *twice*, then typing the 2 letters of the code you're looking for. For instance, to search for BC, strike Pfunc twice, then type bc. If there's a BC code in your file, the cursor will leap to it.

 

Home | Programming | Help Docs | KB Tables | XPL | Xtras | Contact

Page Last Updated: 14 May, 2000