\documentstyle {report} 
%\addtolength{\textheight}{.2\textheight}
%\addtolength{\textwidth}{.3\textwidth} 
\title{Extending EVE using EVEplus}
\author{Allen A. Watson} 
\date{\today} 
\setlength{\parindent}{0in}
\setlength{\parskip}{10pt} 
\pagestyle{headings} 
\begin{document} 
\maketitle
\renewcommand{\thepage}{\roman{page}}
\tableofcontents
\newpage
\renewcommand{\thepage}{\arabic{page}}
\setcounter{page}{1}
% Your document, if short, can omit sections. If numbered sections are
% desired, use \section commands like this example:
% Text begins below next blank line
\chapter{The EVEplus Procedures}
\section{Introduction}

This session deals with extending the TPU-based editor {\sc EVE} using the DCL
command procedures, TPU procedures and documentation provided in the software
package {\sc EVEplus} which is available from the SIG tapes or the DECUS
library. It will discuss the pros and cons of extending {\sc EVE}, present some
hints on compiling TPU procedures, describe briefly the extensions I personally
have made to {\sc EVEplus}, mention some fine points of {\sc EVE} and {\sc
EVEplus} conventions, and present methods of making your editor useful in
several different environments such as Mail and VAXnotes.

Included in the presentation are a few TPU  procedures I have written
to add to the suite of procedures provided with {\sc EVEplus}, as examples of
what can be done to make this editor more liveable, more useful, and to
meet specialized needs; however, detailed discussion of these procedures
is not the main point of the talk.

This session {\em will not} present an introduction to TPU coding;
in fact it assumes you know the basics, or are capable of learning TPU from
sources that will be mentioned.

The basic {\sc EVEplus} distribution is already publically available. I am
placing my {\sc EVEplus} enhancements onto the Languages and Tools SIG tape at
this symposium (and probably the VAX tape as well); they should be publically
available within one to two months. Contact members of the L \& T or VAX SIG
for the best way to get a copy of the tape.

\section{Why Extend EVE?}

So the name of the editor is ``Extensible VAX Editor'', so what?  Should
I extend it just because the name says it is extensible, or are there other
reasons?

\begin{enumerate}
\item Basic {\sc EVE} only scratches the surface of the capabilities of TPU.
For instance, {\sc EVE} provides the ability to use only two editing windows;
there is no such inherent limitation in TPU.
\item To provide more sophisticated interfaces to DCL commands, such as
the Directory command, or to Mail.
\item Because it is very easy; you get large payoffs for little effort.
\item To provide key bindings that are more compatible to your local
installation. (We developed a keypad that is very close to EDT's in order
to capitalize on everyone's EDT experience, and added commands to some of
the VT200 Function Keys.)
\item To add capabilities you miss or envy in other editor programs like
EMACS or VI. I was a long-time user of EMACS, and simply refused to give
up those capabilities. By extending {\sc EVE} to include the ones I wanted
most, I insured I could take them with me to any VAX site.
\end {enumerate}

There {\em are} some reasons {\em not} to extend {\sc EVE}, too, and you
have to face them. If you get used to extensions, you begin to depend on
them. And they are inevitably non-standard; your extensions are not the
same as anybody else's. If you move to another VAX site, you may come in
conflict with their locally extended {\sc EVE}. If you move off VAXen entirely
(God forbid!) {\sc EVE} is simply not available, whereas an editor like
EMACS (or even EDT) exists on multiple operating systems.

For me, these reasons not to extend don't hold enough weight to stop me.
I don't intend to leave the VAX world soon, and am not particularly interested
in working on other operating systems. I can bring my own customized {\sc
EVEplus} with me even if a VAX site has their own version. And if I do have
to work with another editor at times, I seem to be able to switch from one
set of editor vocabulary to another: I still use EDT at times (as in the
Datatrieve Edit command) and even TECO, and I support some EMACS users enough
to remain haltingly fluent in that editor as well.

\section{What is {\sc EVEplus} and Why Use It?}

{\sc EVEplus} is a set of extensions to {\sc EVE} developed by Digital
employees and distributed for free, via the DECUS software tapes and software
library. I heartily recommend it!

Besides the actual extensions to the editor that this package provides,
which are summarized below, {\sc EVEplus} provides an invaluable set of DCL
and TPU procedures that make adding functions into {\sc EVE} as simple as
coding a short TPU procedure and adding one line to the TPU procedure
that builds {\sc EVEplus}, to tell it to include the new {\tt .tpu} file.

To add a new function to our {\sc EVEplus} editor, I do three simple things:

\begin{itemize}
\item Create a TPU procedure and store it in an appropriately named {\tt
.tpu} file in the directory that contains our other {\sc EVEplus} extensions.

\item Add a line to the basic file I call {\tt eveplus\_system.tpu} telling
it to {\em include} the new file.

\item Run the DCL procedure {\tt eve\_build.com}.
\end{itemize}

That's all there is to it!

The hardest part, obviously, is coding the TPU procedure.  So let me say
a few words about learning TPU code.

Basically, TPU is a simple language. It is structured, similar to Pascal;
if you know another structured language TPU will come easily to you. It
does not have a lot of commands to learn. The reference manual is very good,
with some examples showing how to use each of the commands.

There is no TPU  primer, however. The best thing you can have is some examples
to work from, which you can copy and alter to fit your needs. And you have
them!  First of all, DEC kindly provides you with the files {\tt evesecini.tpu}
and {\tt edtsecini.tpu} in {\sc sys\$library}. These are the {\em source
code} for {\sc EVEplus} and for the EDT emulator. Read over these files,
and you will see very clearly how things are done in TPU.  In addition,
you also have the source code for the {\sc EVEplus} extensions.

Finally, the editor itself contains the compiler! Using basic {\sc EVE}
or {\sc EVEplus}, you can write a TPU procedure in a buffer, compile it,
and try it out before adding it to the stored version of the editor. That
process is worth a short section of its own.

\chapter{TPU Programming Techniques}
\section{Writing Your Own TPU Procedure}

If nothing special has been set up for you, get into the EVE editor using
the DCL command {\tt edit/tpu}. Or get into it using your own local version
of that command. Start with an empty buffer, perhaps editing a file called
{\tt test.tpu} that will contain your experimental TPU  procedure.

If you don't have a TPU reference manual handy, online help for all the
TPU commands is available by hitting the DO key and typing {\tt help tpu};
you get a basic blurb that tells you to hit the DO key again for more
information. The second DO opens up the entire TPU help library with
information on every TPU command and how to use it.

If you are writing a procedure that you want to be able to use simply from
within {\sc EVE}, I recommand naming it with a prefix of ``eve\_'', for example
``eve\_text''.  If the procedure has that prefix, you can access it through the
Do key and typing the command name; ``text'' in the above instance.  If you do
not use this prefix, you will have to use a longer command. If you called the
procedure simply {\tt text\_margins}, then to execute it you would hit the Do
key, and type {\tt tpu text\_margins} (using the {\em full procedure name with
underscores}).

To summarize: if a procedure is named {\tt eve\_command\_name}, then {\em
command name} can be used as an {\sc EVE} command by pressing Do and typeing
{\tt command name}; if a procedure begins with anything else other than the
letters ``eve\_'' it can {\em only} be used as a TPU command, by giving the
full procedure name, e.g. {\tt my\_special\_proc} in a TPU procedure, or {\tt
tpu my\_special\_proc} from the {\sc EVE} command prompt.

\section{Sample TPU Procedures}
Here are two simple TPU procedures that sets up different left and right
margins which I use for {\em text} as opposed to {\em programs}; the procedure
{\tt eve\_text\_margins} sets narrower margins making the text easier to read
than 80-column lines.

\begin{verbatim}
     procedure eve_text_margins
     eve_set_left_margin(6);
     eve_set_right_margin(75);
     endprocedure;
     procedure eve_full_margins
     eve_set_left_margin(1);
     eve_set_right_margin(79);
     endprocedure;
\end{verbatim}
                  
These procedures actually don't contain any real TPU commands except {\tt
procedure} and {\tt endprocedure}.  The nice thing about TPU is that a named
procedure becomes available to the TPU compiler as another command; any
undefined name is assumed to be a procedure call. Here, I have used the
predefined procedures {\tt eve\_set\_left\_margin} and {\tt
eve\_set\_right\_margin}. You can assume that any command known to {\sc
EVE} has a corresponding procedure named with the {\tt eve\_} prefix; thus
for the {\sc EVE} command ``bottom'' there is a procedure called {\tt
eve\_bottom}, and so on.

\section{Compiling A Procedure}
Try typing these two procedures into an empty buffer.  Then, compile them
with the following command, typed after pressing the Do key:

\begin{verbatim}
	tpu compile(current_buffer)
\end{verbatim}

Unless you have made typos, the result will be a message at the bottom of
the screen saying {\tt Compilation completed without errors}. You have now
created two new procedures.  Try them out! Press the Do key and type {\tt
text}.  (You don't need the full command name because no other {\sc EVE}
command begins with ``text'' so there is no ambiguity.) Type in a couple
of lines, and you will observe that the text is now falling into the new
margins.  Incidentally, the Fill Paragraph command observes whatever margins
you have set.  Try typing Do and {\tt full} to reset the margins, and then
Do and Fill Paragraph; the paragraph you've typed will be re-adjusted to
the new margin settings.

If you are doing customization only for yourself, you can simply place these
procedures at the start of your {\tt tpuini.tpu} file (procedures must come
before any executable statements in initialization files) and they will
be automatically compiled for you every time you execute {\sc EVE}.

\section{Error Messages}
OK, what if you {\em do} get compilation errors? The error messages go into
the {\sc messages} buffer which is standard in any {\sc EVE}. Use the command
{\tt Buffer} to switch to the {\sc messages} buffer, where you can read
your error messages; then switch back to the buffer your procedure is in,
make the corrections, and compile again.

This is the basic procedure you will use to create new editing procedures
that you can add to your editor. 

\section{Hint on Command Recall}
One time-saving hint: when you have pressed the Do key and see the {\tt
Command:} prompt, your cursor is actually in a buffer called {\sc commands}
that is displayed in a one-line window. So, you can use the Find Key to find
previously typed commands! I find it tedious to type {\tt tpu compile 
(current\_buffer)} over and over; usually what I do is just press Do, then Find,
then {\tt tpu}, and bingo, I'm located on the last line starting with those
letters which is the command I want; I then just hit Return to re-execute the
command! You can also use the Up Arrow key to walk back through the command
buffer line by line to find the command you want. Remember: {\em every command}
you type in via the Do Key is kept in the {\sc commands} buffer for the
duration of your {\sc EVEplus} session.

\chapter{Some Additional EVEplus Procedures}

\section{Procedures in My EVEplus}
Here is a quick list of the TPU  procedures I've added or modified for {\sc
EVEplus}, with a short description:

\begin{description}

\item{{\bf aaw\_erase\_line.tpu}} An alternate Erase Line, which erases 
to end of line without deleting the actual end of line.

\item{{\bf aaw\_nextline.tpu}} To emulate the EDT KP0, moves cursor to start 
of next line according to setting of forward or backward motion.

\item{{\bf aaw\_openline.tpu}} Emulates EDT GOLD KP0 a la EMACS Open 
Line, inserts blank line above current line.

\item{{\bf act\_occurs.tpu}} Specialized version of {\tt eve\_occurs} 
for our resource accounting system, displays every line containing string given
as argument.

\item{{\bf buffer.tpu}} Extension of EVE's Buffer command. Remembers buffer you
came from, offers to return there when next Buffer command executed.

\item{{\bf cursorkeys.tpu}} Alternate cursor movement from arrow keys, 
more like EDT's.

\item{{\bf default.tpu}} Resets default device and directory for file 
input commands and file output commands.

\item{{\bf define\_keys.tpu}} Standard part of {\sc EVEplus}, this file sets 
up the default key definitions for our EVEplus. The keypad looks like EDT, but
there are many other definitions.

\item{{\bf define\_window\_keys.tpu}} Contains key definitions just for 
the extended windowing package I wrote.

\item{{\bf delete\_to\_end\_word.tpu}} The Erase Word command that looks 
like EDT's; erases only from current cursor location to end of word, rather
than erasing the entire word.

\item{{\bf directory.tpu}} Borrowed from another source, and written by
somebody I know only by the initials JLB. Does a listing of any
directory in a buffer and then lets you move the cursor to a file name and
read it in with a single key (Gold-Select in our version, which executes
This File command). The This File command is defined in this procedure also;
it reads in any file from a file spec on which the cursor rests, and works
in any buffer, not just the Directory List buffer. This command helps a
lot when you can't remember the whole file name, at least until DEC gets
around to adding file name completion to {\sc EVE}. Incidentally, the hooks
for doing it are already in the {\sc EVE} source; it will take a fair amount
of effort to implement it cleanly, however.

\item{{\bf dired.tpu}} Borrowed from another source with author unknown,
this is a rudimentary Dired (Directory Editor) command, copied from EMACS, but
incompletely. Usable, but needs work. Allows you to see directory listing, read
in files for edit with single key, or delete them.

\item{{\bf eag\_markers.tpu}} Author: C. D. Beckett. Sets up capability 
of a ring of marks (limit 5) similar to that in some EMACS versions. {\em Gold}
positions of the following three keys operate the commands: {\tt Insert Here}
sets a mark; {\tt Find} goes to previous mark; {\tt Remove} deletes the mark on
which cursor rests.

\item{{\bf end\_of\_line.tpu}} Implements emulation of EDT End Of Line 
command, dependant on forward/backward direction.

\item{{\bf eve\$help\_keypad.tpu}} Internal {\sc EVE} routine, rewritten 
to display the special keypad diagram for {\sc EVEplus}.

\item{{\bf eveplus\_system.tpu}} My version of the special {\sc 
EVEplus} routine that builds the program, including all my routines.

\item{{\bf eve\_advance.tpu}} Emulates the EDT routine to set the direction of
movement forward for Search and various ``move'' commands.

\item{{\bf eve\_append.tpu}} Emulates the EDT Append command; appends selected
region to the Paste Buffer.

\item{{\bf eve\_backup.tpu}} Emulates the EDT routine to set the direction 
of movement backward.

\item{{\bf eve\_change\_case.tpu}} Emulates the EDT Change Case 
command. Changes case of single character, or if a region is selected, switches
case of every character in the region.

\item{{\bf eve\_copytext.tpu}} Copies the selected region into the Paste 
Buffer without deleting it from the current buffer.

\item{{\bf eve\_delete\_window.tpu}} Part of my multi-window package. 
Deletes current window, adding lines to surrounding windows.

\item{{\bf eve\_eof.tpu}} Special routine that sends an End-of-file 
(Control-Z) to the DCL subprocess; useful for getting out of programs that
require a Control-Z to exit.

\item{{\bf eve\_erase\_character.tpu}} Replacement for normal Erase Character;
saves erased character so Undelete Char can work.

\item{{\bf eve\_erase\_to\_eol.tpu}} Emulates EDT command. Erases from current
cursor location to end of line.

\item{{\bf eve\_expand\_window.tpu}} Part of my multi-window package. 
Allows you to expand or shrink windows.

\item{{\bf eve\_fndnxt.tpu}} Emulates EDT Fndnxt command. Finds next occurance
of last-specified search string.

\item{{\bf eve\_help.tpu}} Modification of standard {\sc EVE} Help 
command. First searches {\tt eveplushelp.hlb} so that help for {\sc EVEplus}
routines can be kept in their own help library, leaving the standard {\tt
tpuhelp.hlb} unchanged.

\item{{\bf eve\_next\_window.tpu}} Part of my multi-window package. Moves the
cursor to the next window downward on the screen; from last window cycles
back to first.

\item{{\bf eve\_noonly.tpu}} Part of my multi-window package. Cancels the Only
Window command (which see).

\item{{\bf eve\_occurs.tpu}} Emulation of Emacs Occurs command. Displays 
all lines in the current buffer which contain a given text string. Good for
checking references to variables, displaying sequence of Runoff Header Level
commands, etc.

\item{{\bf eve\_one\_window.tpu}} Minor revision to standard {\sc EVE} 
One Window command to better coordinate with my windowing package.

\item{{\bf eve\_only\_window.tpu}} Part of my multi-window package. 
This command makes the current window the only window displayed by actually
mapping a new, full screen window over any existing windows. Allows you to blow
the current window up to full screen. The corresponding Noonly Window command
undoes this, restoring the original multi-window mapping.

\item{{\bf eve\_section.tpu}} Emulates EDT Section command; does a 
Previous Screen or Next Screen command depending on the current setting of
direction.

\item{{\bf eve\_split\_window.tpu}} Part of my multi-window package. Splits 
the current window into two approximately equal windows and offers to read in a
new file into the newly created window.

\item{{\bf eve\_time.tpu}} Displays the current time and date in the 
message window at the bottom of the screen.

\item{{\bf eve\_transpose\_lines.tpu}} Exchanges current line with line above
it.

\item{{\bf eve\_two\_windows.tpu}} Revision of the standard {\sc EVE} 
Two Windows command to better work with my window package.

\item{{\bf eve\_undelete\_char.tpu}} Inserts last character deleted with Erase
Character. Useful for copying non-typeable characters like Escape.

\item{{\bf execute\_dcl\_line.tpu}} Takes a copy of the line the cursor 
is currently on and sends it to the DCL subprocess for execution within {\sc
EVEplus}. Useful for repeating long commands. I bind this to Gold-Return.

\item{{\bf execute\_eve.tpu}} Written by Valerie Matthews of Digital, 
this procedure executes a file or a buffer containing a set of {\sc EVE}
commands, so that you can write {\em command procedures} in {\sc EVE} code, one
command per line. Contains Execute Eve File and Execute Eve Buffer procedures.

\item{{\bf extract\_to\_file.tpu}} Writes the selected region to a 
specified file. Uses device and directory set by Default commmand, if one
exists.

\item{{\bf fetch\_file.tpu}} Written by Valerie Matthews of Digital. Revised 
by me to use device and directory set by Default command. This is a modified
Get File, which gives you the option of clobbering the buffer if it already
exists. Allows you, for instance, to read back original copy after you have
accidentally destroyed copy in buffer.

\item{{\bf fill\_paragraph.tpu}} Modification of standard {\sc EVE}
Fill Paragraph command. Recognizes lines beginning with \LaTeX\ commands as
paragraph delimiters so you can use the command conveniently in editing
\LaTeX\ source files. Also fixes a bug that sometimes left a single blank
at the end of paragraphs.

\item{{\bf findhelp.tpu}} Not a part of {\sc EVEplus}, this procedure 
is something I read in and compile when I am editing a long Help file. It
searches for a line beginning with a digit, which is the delimiter between
topics in a help file.

\item{{\bf fixhelp.tpu}} Not a part of {\sc EVEplus}, this is another example
of a specialized procedure I use in editing help files. It finds lines starting
with a string of blanks followed by a digit and removes the blanks.

\item{{\bf flush.tpu}} Emulates the Emacs Flush command. This locates 
and erases all lines containing a particular string. Use it to strip comments,
eliminate all of a certain file type (e.g. {\tt .exe}) from a directory
listing, etc. See also Keep.

\item{{\bf get\_file.tpu}} Revision to standard {\sc EVE} Get File, to 
use default device and directory set by Default command.

\item{{\bf home.tpu}} Moves the cursor to the upper left corner of the window.
I bind this to Gold-Prev Screen.

\item{{\bf include\_buffer.tpu}} Works like Include File to insert the 
contents of a named buffer.

\item{{\bf indent.tpu}} Primitive indentation command, needs tidying 
up. Prompts for number of lines to indent, number of spaces, and inserts (or
deletes if number is negative) that number of spaces at the beginning of each
line.

\item{{\bf init\_new\_window.tpu}} Not part of {\sc EVEplus}, but a 
good example of a simple window manipulation procedure.

\item{{\bf keep.tpu}} Inverse of the Flush command, this procedure erases all
lines that {\em do not} contain the specified string, keeping only those
that do.

\item{{\bf list\_keys.tpu}} Author unknown (JLB?). Lists all defined 
keys (incredibly useful when you start going crazy with key definitions) in a
buffer called {\tt list keys}. Contains long comments about how to interpret
keynames in TPU.

\item{{\bf locate\_key.tpu}} Written by me to build on List Keys, 
this procedure accepts either a command name or key name (e.g. F17) and
displays the line(s) from the List Keys buffer which contains it, using the
Occurs procedure. (See how incestuous this stuff gets?) If you want to know
whether or not the Split Window command is on a key somewhere, just press Do
and type {\tt locate split\_Window}, and voila! (You must include the
underscores for procedure names having more than one word.) If the List Keys
command hasn't been run first, Locate Key will run it.

\item{{\bf mail.tpu}} My biggest and most complex procedure, this provides 
a full interface to the VMS Mail utility from within {\sc EVEplus}. At the time
of writing the actual command used to execute it is {\tt domail}, to avoid
conflict with the following procedure name. I intend to rename the next
procedure so this one can be called simply {\tt mail}. I do all my mail now
using this procedure. May still have one or two minor bugs; I'm still hacking
at it. When DEC documents callable Mail, I'll probably revise to take advantage
of that. For now it runs Mail in a special subprocess and passes commands to it
there.

\item{{\bf mail\_a\_buffer.tpu}} Mails the contents of the current buffer 
to the user(s) you name.

\item{{\bf move\_paragraph.tpu}} Moves the cursor to the next end of 
paragraph, forward or back depending on the direction set with Advance or
Backward.

\item{{\bf move\_sentence.tpu}} Moves the cursor to the next end of sentence,
depending on the direction set.

\item{{\bf newout.tpu}} Allows you to change the output file name 
associated with the current buffer. One of my first procedures, written before
I learned how to use optional parameters, so it takes no parameter but always
prompts for the new file name.

\item{{\bf page.tpu}} Moves cursor to next Form Feed character occurring at 
the beginning of a line; emulates the EDT Page command.

\item{{\bf preserve\_buffers.tpu}} Writes out all modified buffers (unless 
they are no-write), but keeps the buffers in memory. A modification of the
regular {\sc EVEplus} routine Release Buffers, which also deletes the buffers
that are written out.

\item{{\bf read\_file.tpu}} Minor revision of Get File that sets the buffer No
Write after reading in the file.

\item{{\bf read\_mail.tpu}} My first attempt at a mail interface, still there
as part of {\sc EVEplus}, but doomed to extinction. See {\tt mail.tpu}.

\item{{\bf send\_to\_dcl.tpu}} Sends the entire current buffer as input to the
DCL subprocess. It could be used, for example, to send a series of
DCL lines in a buffer to the DCL process. Note that the DCL subprocess must
already exist for this to work.

\item{{\bf shell\_sort.tpu}} Modification to the shell sort routine that comes
with standard {\sc EVEplus}. I modified it to allow you to sort a defined
region as well as an entire buffer.

\item{{\bf spell.tpu}} The Spell command will execute a spelling checker 
against the current buffer, reporting the results in the DCL buffer. If you are
familiar with the spelling checker used, and use \LaTeX\ frequently, you might
want to add common \LaTeX\ commands to its exception dictionary, as it reports
most of them as possible errors.

The spelling checker used is the one that came as part of Jim Downward's
VAX Programmer Workbench contribution to the VAX SIG tapes a couple of years
back; I believe he borrowed the program from a Denison University submission.

The {\tt spell.tpu} procedure came to me via another programmer at Goldman
Sachs, Seth Silverstein; he had modified it from one he obtained from I
don't know where which invoked DECspell, making it invoke the Decus program
we had. I further fixed it up, mainly eliminating a couple of things that
caused it to choke now and then. The original authors, from the comments,
include the following: David Snow, Dave Griffin, Mike Taylor, the
mysterious ``JLB'', and ``RAB''. The whole thing is a good example of Decus
synergy.

\item{{\bf transpose\_char.tpu}} Transposes the two characters just to the 
left of the cursor; good for quick fix to common typos.

\item{{\bf whitespace\_compress.tpu}} Reduces all whitespace characters (tab,
spaces) on either side of cursor to a single space; or at start of line,
removes them all. Actually just a shell around a procedure internal to {\sc
EVE}, providing a name beginning with {\tt eve\_} so that it can be invoked
as an {\sc EVE} command.

\item{{\bf wildcard\_search.tpu}} Modification to the wildcard search routine
that comes with {\sc EVEplus}. I fixed a bug in the start and end of line
indicators, and added the ability to search for any one of a group of
characters, e.g. ``[12345]X'' will find ``1X'', ``2X'', etc.

\item{{\bf write\_file.tpu}} Minor change to {\sc EVE} Write File, causing it
to use the device and directory specified by the Default command (if any).
Also fixed a strange bug when Write File is issued from a buffer created
by the Buffer command with no output file. Behavior {\em was}: you were
prompted for a file name; if you pressed Return without giving one, a file
called ``.;'' was created! I changed this to default to a file name of {\tt
file.txt} and to issue an informational message to that effect.

\item{{\bf zap.tpu}} Erases characters from current cursor location up to and
including the single character argument. E.g., {\tt zap ;} will erase up
to and including the next semicolon in the buffer. Direction always forward.
Erased text saved in Paste Buffer and can be recalled with Insert Here.

\end{description}

\chapter{Conventions and Finer Points}

The {\tt zap.tpu} procedure illustrates a few conventions and fine points
about TPU  programming specifically for {\sc EVEplus}, which I'd like to
discuss here. There are several things that I've learned by trial and error
in modifying and adding to {\sc EVEplus} that should save you some time
if I pass them along.

\begin{verbatim}
procedure eve_zap(the_arg)
! Procedure deletes text from current location up to 
! and including a target character given as a parameter.
local the_target, ! Character to zap to
      the_range,  ! Range containing text to zap
      zap_start,
      zap_end;    ! Start and end of region to delete.

  the_target := the_arg;

    if (the_arg = '') then
        the_target := read_line('Zap to what character: ',1);
    endif;

    zap_start := mark(none);    ! Remember start
    zap_end := end_of(search(the_target,forward));
    the_range := create_range(zap_start,zap_end,none);
    position(paste_buffer);
    erase(paste_buffer);
    move_text(the_range);
    position(zap_start);
    update(current_window);
endprocedure;

procedure tpu$local_init
    eve$arg1_zap := eve$arg1_buffer;
endprocedure;
\end{verbatim}

\section{Initializing Arguments}

When a procedure (such as {\tt zap}) requires an argument, the argument
must be initialized before the procedure is used or it will not work properly.
{\sc EVEplus} uses a special procedure to do this call {\tt tpu\$local\_init}.
An example of such a procedure is shown here with the main body of {\tt
zap.tpu}.

The particular convention shown here works only if you name your procedures
with names starting with {\tt eve\_}.  The name of the global variable you
must initialize is formed by replacing the letters {\tt eve\_} in the procedure
name with the letters {\tt eve\$arg1\_}; thus the first and only argument
to {\tt eve\_zap} is called {\tt eve\$arg1\_zap}. The value assigned to
it is {\tt eve\$arg1\_buffer}, a global variable defined in {\sc EVE}. This
variable seems to work to initialize any kind of argument and any number
of arguments.

When you are first testing a new procedure with arguments, include such
an initialization procedure at the end, after the main procedure. Compile
the procedures using {\tt tpu compile(current\_buffer)}, and then {\em execute}
the initialization procedure with {\tt tpu execute(tpu\$local\_init)}. You
need do this only once; you can then test, modify, recompile, and so on
as often as you like without re-initializing. If you end your editing session
and return later to test more, you will have to initialize again.

What I often do is to comment out the {\tt procedure} and {\tt endprocedure}
statements for the initialization procedure, and then use {\tt tpu execute(
current\_buffer)} to compile the procedure {\em and execute} the initialization
code which follows. If you do this, be sure to uncomment the two procedural
statements before storing your final version for use in {\sc EVEplus}.

The reason you want the initialization code contained in a {\tt
tpu\$local\_init} procedure is that when the DCL procedure {\tt eve\_build.com}
runs, all of the procedures named {\tt tpu\$local\_init} get appended together
as one grand initialization procedure that gets run each time you start
up {\sc EVEplus}.

\section{Modifying Arguments}

{\em You cannot modify an argument to a procedure.} If you want to allow
the user the option of omitting the argument and being prompted for the
value if it is missing, you should assign the value passed in the argument
to a local variable, and then test and prompt for a new value using that
local variable.

{\tt zap.tpu} does this in this statement:
\begin{verbatim}
	  the_target := the_arg;
\end{verbatim}

\section{Using the Paste Buffer}

The {\em Paste\_Buffer} is the internal name ({\em buffer variable} name) of the
buffer that is used by the Remove command to stash the deleted text, and the
contents of the Paste\_Buffer are what the Insert Here command inserts. The Zap
command uses it in the same way. The external name used to refer to this buffer
(the name you would give as an argument to the Buffer command to switch to
this buffer) is {\tt insert here}; this is often the case with {\sc EVE} system
buffers, that is, the external and internal names are different. 

If you want to find what {\em buffer variable name} is used to point to
a particular buffer within {\sc EVE} or {\sc EVEplus}, you will need to
search through the source code looking for a {\tt create\_buffer} statement
containing the {\em external name} you are familiar with. It could also
be a line using an {\sc EVE} internal procedure called {\tt eve\$init\_buffer},
as in the following example which creates the Insert Here buffer:
\begin{verbatim}
   paste_buffer := eve$init_buffer ("Insert Here", 
       "[End of Insert Here buffer]");
\end{verbatim}

The varible on the left of the assignment statement is what I am calling
the internal name, that is, a variable containing a buffer pointer to the
buffer in question. In TPU code it is far easier to refer to a buffer by
this internal name than it is to use the external name, which requires a
search through the list of existing buffers to find a match. This is what
I have done in the Zap procedure.

\section{WHAT Source Code?}

In case you are not aware of it, you have the TPU source code for DEC's
original {\sc EVE}, as well as the {\sc EVEplus} source (from the SIG tape)
and my source (on the upcoming tape).

{\tt sys\$library:evesecini.tpu} contains the source for {\sc EVE} itself.
This files contains 6161 lines of TPU source code, and is the best teaching
tool I have found for how to use TPU. I've never read the entire thing,
although I keep meaning to because it surely would be worth it. There are
dozens of internal routines, some of which I've stumbled over and used,
but I'm sure some of my procedures could be shortened by using more of them.
You can almost always find something in {\tt evesecini.tpu} that does something
close to what you want to do, and just modify it, which is lots faster than
figuring it all out from scratch.

Also, if you don't like the way some particular {\sc EVE} command works,
you can extract its source, modify it to your liking, and include it in
the build procedure for {\sc EVEplus}; your new version will replace the
old one. I did that, for instance, with the four cursor movement procedures
bound to the Arrow Keys.

\chapter{Using Your New Editor}

This chapter will discuss how to use your new editor once you've created
it.  Remember, you can store the Section File created by the {\sc EVEplus}
build procedure anywhere you want, and you can have a personal copy if you
are so idiosyncratic that the system-wide copy doesn't satisfy you.

Incidentally, if you use the files straight off my contribution to the SIG
tape, you should modify the last statement in {\tt eveplus\_system.tpu}
which saves the section file; change it to use the directory you want to
use. I doubt you have a directory called {\tt common\_disk:[syslib]}, which
is where we store our copy.

\section{Normal DCL-level use}

First of all, you don't have to destroy the original {\sc EVE} to have {\sc
EVEplus} around. You really shouldn't, as other things on the system may
refer to it. That's why I name the section file {\tt eveplus} instead of
{\tt eve}, and in fact store it in a different directory. In the examples
that follow I am assuming that the section file created by the build procedure
is:
\begin{verbatim}
    common_disk:[syslib]eveplus.tpu$section
\end{verbatim}

If you use a different device, directory, or file name, you would substitute
them in the commands where you see the above file specification used.

There are two different ways to set up a foreign command to access {\sc
EVEplus} easily directly from DCL level.

\subsection{Specifying the Section File}

Let's say we've decided that the foreign command {\tt eve} will access the
{\sc EVEplus} editor. Define the command like this (in your {\tt login.com}
file to have it every time you log in):
\begin{verbatim}
   eve :== edit/tpu/section=common_disk:[syslib]eveplus
\end{verbatim}

\subsection{Using A Logical Name}

An even easier way is to define the logical name {\tt tpusecini} to point
to the section file, and define the foreign command without the section
file specification. This has other advantages I'll discuss in a moment.
Put these lines into your {\tt login.com} file:
\begin{verbatim}
   eve :== edit/tpu
   define/job tpusecini common_disk:[syslib]eveplus
\end{verbatim}

I use the {\tt /job} qualifier to insure that the logical name is known
to any subprocesses I create, no matter how they are created. In most cases
you can leave this off (and Job Table space is very limited so you may want
to do that).

\section{Using EVEplus as Your Mail Editor}

You can have the Mail utility use EVEplus as your editor very easily. First,
create a file called {\tt mailedit.com} containing the following code (modified
with appropriate device and directory specs):
\begin{verbatim}
$ !
$ ! Command procedure to invoke an editor for MAIL.
$ !
$ ! Inputs:
$ !
$ !	P1 = Input file name.
$ !	P2 = Output file name.
$ !
$ ! If MAIL$EDIT is undefined, MAIL will invoke callable EDT.
$ ! If MAIL$EDITis defined to be a command procedure,
$ ! MAIL will create a subprocess to edit the mail.
$ !
$ ! Note that this procedure is run in the context of a subprocess.
$ ! LOGIN.COM is not executed.  However, all process logical names
$ ! and DCL global symbols are copied.
$ !
$ ! The default directory is the same as the parent process
$ !
$ DEFINE /USER SYS$INPUT 'F$TRNLNM("SYS$OUTPUT")'
$ IF P1 .EQS. "" THEN GOTO NOINPUT
$ EDIT/TPU/SECTION=COMMON_DISK:[SYSLIB]EVEPLUS /OUTPUT='P2' 'P1'
$ EXIT
$NOINPUT:
$ EDIT/TPU/SECTION=COMMON_DISK:[SYSLIB]EVEPLUS 'P2'
$ EXIT
\end{verbatim}

Then define the logical name {\tt mail\$edit} to point to the file you've
created.

If you now enter Mail and issue the command {\tt send/edit}, Mail will spawn
a subprocess and use {\sc EVEplus} as the editor.

This works pretty well, but I wasn't really satisfied with it because, since
Mail was having to spawn a subprocess, I couldn't use the commands that
require a ``callable'' editor, such as the Edit command. Also, when the
systems got really heavily loaded, the Spawn command took forever!

So I found an alternate way, undocumented that I know of. I think I found
it on the DecusServe system, I'm not sure.  Anyhow, it's very simple.

Forget about {\tt mailedit.com}. You don't need it. Just make sure you have
these two logical names defined:
\begin{verbatim}
   define mail$edit callable_tpu
   define tpusecini common_disk:[syslib]eveplus
\end{verbatim}

Guess what happens?  Mail is now satisfied that it has a callable editor,
so the Edit command works. Instead of spawning a subprocess, Mail calls
TPU directly, and because {\tt tpusecini} is pointing to my personal
{\sc EVEplus} section file, {\em that} is the editor I get. Even my
initialization file is run (I define the logical name {\tt tpuini} to point
to it). And there is no spawn of a subprocess, so that even on a non-loaded
system entry into the editor is considerably faster than previously.

If you would like the use of an editor for appropriate mail commands to be your
default, you can set that up as well. (I've gotten so I can't {\em stand}
writing a message without the editor -- you know, the one line at a time
thing you usually get in Mail.) Just redefine the Mail command in your {\tt
login.com} file like this:
\begin{verbatim}
  mai*l == "mail/edit=(send,reply,forward)"
\end{verbatim}

This will cause Mail to use your editor for any Send, Reply, or Forward
command unless you add the {\tt /noedit} qualifier. It's great!

While I'm on conveniences in Mail, even though this is a talk on {\sc EVEplus},
let me throw in this one: you can set up additional key definitions in a
{\em mail initialization procedure}. Only Define/Key commands work in it,
but here's a for instance. Create a file like this, and then define the
logical name {\tt mail\$init} to point to it:
\begin{verbatim}
   DEFINE/KEY/TERMINATE F17 "FILE TRASH OLDMAIL.MAI"
   DEFINE/KEY/TERMINATE F18 "FILE READING"
   DEFINE/KEY/TERMINATE F19 "FILE TODO"
   DEFINE/KEY/TERMINATE F20 "ATTACH/PARENT"
   DEFINE/KEY/TERMINATE PF4 "DIR TODO"
   DEFINE/KEY/TERMINATE PERIOD DELETE
\end{verbatim}

Obviously you would define commands useful to {\em you}; these are the ones
I define, using folder names I commonly refer to.  You {\em did} know that
Mail has most of the keypad keys defined for you, didn't you? If not, try
typing {\tt help keypad} while in Mail.

\section{Using Your Editor In VAXnotes}

This one is {\em real} easy. First make sure you have the logical name {\tt
tpusecini} defined to point to your section file.  Then, in VAXnotes, do
the following:
\begin{verbatim}
   set profile/editor=tpu
\end{verbatim}

That's all there is to it! VAXnotes will now use your {\sc EVEplus} section
file instead of the built-in editor, which is {\em like} {\sc EVE} but is
not identical to it (for one thing it has a keypad like EDT's, as does my
version of {\sc EVEplus}; they are so alike I can use either one without
realizing, most times, which one I am in, except when I try one of my special
commands).

Specifying ``tpu'' as your editor is not something that the VAXnotes
documentation or help files tell you that you can do. I found it by accident!
I specified ``tpu'' instead of ``eve'', and the command accepted it. Puzzled,
I wondered what would happen.  I found that if the logical {\tt tpusecini}
was not defined, you got standard {\sc EVE}; if it was defined, you got
the section file it called for! Since this is an undocumented feature there
is no guarantee that it will work forever.

There is a slight cost to this.  First, the built-in editor that comes with
Notes will automatically go into two-window mode when you Reply to a note.
My {\sc EVEplus} does not do that (although when I have time...).

Second, the method I describe below for defining additional key bindings
in the Notes editor will almost surely not work if you have told Notes to
use a different editor. Actually, since the keypads in the two editors are
so similar, I've gotten used to using the built in editor and doing without
the extra commands, but I did use my own editor in Notes for months and
it works perfectly well.

As an aside, I wish the VAXnotes distribution included the TPU source for
the editor, just as {\sc EVE} itself does; that would make it a lot easier
to borrow the missing functionality and add it to {\sc EVEplus}.

\section{Defining Additional Keys in VAXnotes}

It is possible to define additional keys for use at the NOTES prompt,
and when in NOTES' built-in editor.  The following can serve
as a guide.

To use NOTES\$COMMAND, create a file with the TPU define\_key
statements, similar to below.  Then DEFINE the logical name
NOTES\$COMMAND to point to the file.  NOTES will process the commands
when it starts up. As indicated in the last section, I am not at all sure
this will work if you have substituted {\sc EVEplus} for the built-in editor
in Notes. I know it works if you use the built-in editor.

\begin{verbatim}
!
! Keys in notes
!
!
! Define the following keys at the notes prompt
!
!	gold ?	Go to the message buffer
!	ctrl/n	Go into EVE
!	ctrl/d	Do a directory of the current conference from the
!		 end to the beginning
!	pf3	Close the current conference
!
define_key ("notes$do_command ('EVE BUFFER MESSAGES')",
  key_name ('?', shift_key), "msg buf", notes$kt_user_keys);
define_key ("notes$do_command ('EVE')", ctrl_n_key, 
   "EVE", notes$kt_user_keys);
define_key ("notes$do_command ('DIR LAST-1')", ctrl_d_key,
   "DIR", notes$kt_user_keys);
define_key ("notes$do_command ('CLOSE')", pf3, 
   "close", notes$kt_user_keys);
!
! Keys in the editor
!
! Define the following keys in the built-in editor
!
!	ctrl/n	Go back to NOTES
!	ctrl/p	Switch to the other window if two 
!		windows are on the screen
!	gold 1	Make only one window on the screen
!	gold 2	Make two windows on the screen
!	gold b	Prompts for a buffer name, then 
!		switches to that buffer
!	gold i	Prompts for a file to include at 
!		the cursor location
!	gold f	Fills the current paragraph
!	gold v	Prompts for a file, then reads 
!		it into a new buffer
!	gold ?	Switch to the message buffer
!	gold [	Set the screen width to 80
!	gold ]	Set the screen width to 132
!
define_key ("eve_notes", ctrl_n_key, 
	"NOTES", eve$x_user_keys);
define_key ("eve_other_window", ctrl_p_key, 
	"other window", eve$x_user_keys);

define_key ("eve_one_window", key_name ('1', shift_key), 
	"one window", eve$x_user_keys);
define_key ("eve_two_windows", key_name ('2', shift_key), 
	"two windows", eve$x_user_keys);
define_key ("eve_buffer (eve$kt_null)", 
	key_name ('b', shift_key), "buffer", eve$x_user_keys);
define_key ("eve_include_file (eve$kt_null)", 
   key_name ('i', shift_key), "include file", eve$x_user_keys);
define_key ("eve_fill_paragraph", key_name ("F", shift_key),
	"fill paragraph", eve$x_user_keys);
define_key ("eve_get_file (eve$kt_null)", 
   key_name ('v', shift_key), "get file", eve$x_user_keys);

define_key ("eve_buffer ('MESSAGES')", key_name ("?", shift_key),
	"message buffer", eve$x_user_keys);
define_key ("eve_set_width (80)", key_name ("[", shift_key),
	"width 80", eve$x_user_keys);
define_key ("eve_set_width (132)", key_name ("]", shift_key),
	"width 132", eve$x_user_keys);
\end{verbatim}

\section{Keeping a Spawned EVEplus}

One of the most useful ways to use {\sc EVEplus} is to spawn a subprocess
to run it, and then just Attach back and forth between the two processes.
Because you can do so much from within the editor it is often not necessary
to leave it for common things such as simple DCL commands or (with my
procedures) processing your mail. But when you need to do extensive DCL
work, or need to run a program that will take over screen control, you must
leave the editor.  Having two processes, one for DCL and one for editing,
makes this a much quicker operation.

I've written a DCL procedure to do the Spawning for me because it sets up
several other things as well. First, the F20 key is defined {\em at DCL level}
to attach specifically to the {\sc EVEplus} subprocess, by name; {\em within
the editor} the F20 key is defined to do an Attach To Parent command, which
attaches back to the originating process. This allows the same key to toggle
back and forth between DCL and {\sc EVEplus}.

Second, the process remembers the spawned subprocess and prevents you from
accidentally spawning a second, third, or fourth subprocess (believe me I've
done this!).

Third, it provides a mechanism (see comments at end of the procedure) for
easily reading in files if you type a second {\tt eve filespec} command,
forgetting you've already got a spawned editor waiting for you.

The benefits of having a spawned {\sc EVEplus} in a subprocess include:

\begin{itemize}

\item Quick transfer in and out of the editor

\item Editing session undisturbed by leaving it, waiting for you when you
return

\end{itemize}

The drawbacks to spawning an editor subprocess include:

\begin{itemize}

\item Too many people doing this could double the number of processes on
your system, or more than that if they use both DCL and Mail subprocesses
{\em within} {\sc EVEplus}.

\item By staying in the editor a long time you run greater risk of losing
something you've modified. The journal files are almost useless for recovering
editing sessions if you have executed any DCL commands within the editor,
and even if you have not done that, restoring the total environment in which
you started the session is often impossible. This means you need to make
frequent use of the Preserve Buffers command, or individual Write File
commands.

\end{itemize}

Having said that, here's the DCL command procedure I use to spawn {\sc EVeplus}.
I define my {\tt eve} command to ``@'' this file instead of invoking {\tt
edit/tpu} directly:

\begin{verbatim}
$!+++ Starts up EVE in subprocess; re-attaches to it if it exists.
$!
$ USERNAME = f$edit(f$getjpi("","username"),"trim")
$ oldmes=f$environment("message")
$ mesoff := SET MESSAGE/NOFACILITY/NOIDENT/NOSEVER/NOTEXT
$ MESON = "SET MESSAGE"+oldmes
$! If EVE subprocess already exists, attach to it.
$ if f$type(EVEPID) .EQS. "" then goto SPAWNIT
$ on warning then goto spawnit
$ mesoff
$ if f$getjpi(EVEPID,"PID") .eqs. "" then GOTO SPAWNIT
$! Add ability to read in file when doing attach!!
$ IF P1 .EQS. "" THEN GOTO NOPARAM
$ WRITE SYS$OUTPUT "Use Line Feed or CTRL/J  to read in ''P1'"
$ on warning then continue
$ DELETE/NOLOG EVECMD.TMP;*
$ OPEN/WRITE EVE_COMFILE SYS$SCRATCH:EVECMD.TMP
$ WRITE EVE_COMFILE "GET FILE ''P1'"
$ CLOSE EVE_COMFILE
$NOPARAM:
$ WRITE SYS$OUTPUT "Attaching to existing EVEplus subprocess..."
$ WAIT 00:00:02
$ ON WARNING THEN GOTO NOEVE
$ ATTACH 'EVEPROCESS'
$ if f$getjpi(EVEPID,"PID") .eqs. "" then -
	delete/symbol/global EVEPID
$ meson
$ EXIT
$SPAWNIT:
$! Spawn an EVE subprocess, passing the file name.
$ if f$type(EVEPID) .NES. "" THEN -
  DELETE/SYMBOL/GLOBAL/NOLOG EVEPID  
$! Use PID of current proc as part 
$! of subproc name, 25-MAR-1987
$ MYPID = F$EXTRACT(4,4,"''F$GETJPI("","PID")'")
$ DEFINE/KEY/TERMINAL/NOLOG F20 "ATTACH EVE''MYPID'"
$ EVEPROCESS :== EVE'MYPID'
$ meson
$ DEFINE/USER SYS$INPUT SYS$COMMAND
$ SPAWN/PROCESS=EVE'MYPID' EDIT/TPU-
  /SECTION=COMMON_DISK:[SYSLIB]EVEPLUS -
 'P1' 'P2' 'P3'
$! Get PID of EVE subprocess and save in global symbol
$ FOUND_IT = "N"
$ mesoff
$ on warning then goto noeve1
$ define/user sys$output pid.tmp
$ show proc EVE'MYPID'
$ on warning then continue
$ open/READ pidfile SYS$LOGIN:pid.tmp
$ read pidfile pidline ! Skip first line
$ read pidfile pidline
$ close pidfile
$ delete/nolog SYS$LOGIN:pid.tmp;*
$ PID = f$element(1," ",pidline)
$ on warning then goto END_SPAWN
$ PROC_NAME = f$getjpi(PID,"PRCNAM")
$ PROC_NAME = F$EDIT(PROC_NAME,"TRIM")
$ if proc_name .nes "EVE''MYPID'" then goto NOEVE
$ FOUND_IT = "Y"
$END_SPAWN:
$ if .not.FOUND_IT then goto NOEVE
$ EVEPID == PID
$ meson
$ EXIT
$NOEVE:
$ write sys$output "No EVE subprocess found for user ",username
$NOEVE1:
$ DELETE/SYMBOL/GLOBAL/NOLOG EVEPID
$ meson
$ EXIT                                               
$!
$! Comments and revision history.
$! AUTHOR: Allen Watson, 13-JAN-1986
$! To use this procedure, in your LOGIN.COM, define 
$! symbol EVE to execute this procedure, for example:
$!    $	EVE :== @SYS$COM:SPAWNEVE.COM
$! The procedure defines the F20 key for VT200 type
$! terminals to do an appropriate ATTACH command, so that
$! from within EVE, F20 switches to the parent process; in
$! the parent process, F20 re-attaches to EVE.  Once you
$! have created an EVE subprocess, if you forget to use F20
$! and type another EVE command line, this procedure will
$! automatically find the existing subprocess and attach to
$! it; you can then use the CNTRL/J KEY to read in the new
$! file named on the command line.
$!
$! Remember, when you leave EVE via the F20 key (ATTACH),
$! the buffers you have edited are NOT automatically written
$! to disk.  You should get in the habit of using the WRITE
$! command within EVE to save updated buffers.
$!
$! REVISION: 18-FEB-1986 AAW
$! Rewrote way of finding and using PID of eve subprocess so
$! that no error messages occur, and when EVEPID is left
$! defined after an Exit from EVE direct to DCL, it is
$! checked for validity before being used.  SPAWNEVE used to
$! fail once in that case, then spawn correctly; now it
$! works right the first time.  Also removed F$PID loop to
$! avoid checking all processes; now look directly at user's
$! EVe subprocess using SHOW PROC into a temp file.  Takes
$! slightly longer but has less adverse effect on system
$! overall.
$! 25-MAR-1987
$! Changed name of subprocess to EVEnnnn where "nnnn" is
$! last four digits of the parent process.  This allows
$! users to have spawned EVE's in more than one session on
$! the same system.
$! Removed /COMMAND qualifier on EDIT/TPU command to allow
$! users to use their own TPU init file.
$! 22-OCT-1987
$! Removed (by commenting out) the SET TERMINAL/INQUIRE and
$! WAIT commands
\end{verbatim}

% End of text
\end{document}
